Index: 3rdParty_sources/versions.txt
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/versions.txt,v
diff -u -r1.2 -r1.3
--- 3rdParty_sources/versions.txt	22 Aug 2012 17:30:39 -0000	1.2
+++ 3rdParty_sources/versions.txt	30 Aug 2012 16:24:44 -0000	1.3
@@ -11,6 +11,8 @@
 
 Commons HttpClient 3.0
 
+Commons Lang 2.0
+
 Hibernate Core 3.3.1 GA
 
 jbosscache 3.1.0.CR1
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/ArrayUtils.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/ArrayUtils.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/ArrayUtils.java	30 Aug 2012 16:24:42 -0000	1.1
@@ -0,0 +1,2274 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * 
Operations on arrays, primitive arrays (like int[]) and primitive wrapper arrays 
+ * (like Integer[]).
This class tries to handle null input gracefully.
+ * An exception will not be thrown for a null
+ * array input. However, an Object array that contains a null
+ * element may throw an exception. Each method documents its behaviour.
Object array.
+     */
+    public static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
+    /**
+     * An empty immutable Class array.
+     */
+    public static final Class[] EMPTY_CLASS_ARRAY = new Class[0];
+    /**
+     * An empty immutable String array.
+     */
+    public static final String[] EMPTY_STRING_ARRAY = new String[0];
+    /**
+     * An empty immutable long array.
+     */
+    public static final long[] EMPTY_LONG_ARRAY = new long[0];
+    /**
+     * An empty immutable Long array.
+     */
+    public static final Long[] EMPTY_LONG_OBJECT_ARRAY = new Long[0];
+    /**
+     * An empty immutable int array.
+     */
+    public static final int[] EMPTY_INT_ARRAY = new int[0];
+    /**
+     * An empty immutable Integer array.
+     */
+    public static final Integer[] EMPTY_INTEGER_OBJECT_ARRAY = new Integer[0];
+    /**
+     * An empty immutable short array.
+     */
+    public static final short[] EMPTY_SHORT_ARRAY = new short[0];
+    /**
+     * An empty immutable Short array.
+     */
+    public static final Short[] EMPTY_SHORT_OBJECT_ARRAY = new Short[0];
+    /**
+     * An empty immutable byte array.
+     */
+    public static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
+    /**
+     * An empty immutable Byte array.
+     */
+    public static final Byte[] EMPTY_BYTE_OBJECT_ARRAY = new Byte[0];
+    /**
+     * An empty immutable double array.
+     */
+    public static final double[] EMPTY_DOUBLE_ARRAY = new double[0];
+    /**
+     * An empty immutable Double array.
+     */
+    public static final Double[] EMPTY_DOUBLE_OBJECT_ARRAY = new Double[0];
+    /**
+     * An empty immutable float array.
+     */
+    public static final float[] EMPTY_FLOAT_ARRAY = new float[0];
+    /**
+     * An empty immutable Float array.
+     */
+    public static final Float[] EMPTY_FLOAT_OBJECT_ARRAY = new Float[0];
+    /**
+     * An empty immutable boolean array.
+     */
+    public static final boolean[] EMPTY_BOOLEAN_ARRAY = new boolean[0];
+    /**
+     * An empty immutable Boolean array.
+     */
+    public static final Boolean[] EMPTY_BOOLEAN_OBJECT_ARRAY = new Boolean[0];
+    /**
+     * An empty immutable char array.
+     */
+    public static final char[] EMPTY_CHAR_ARRAY = new char[0];
+    /**
+     * An empty immutable Character array.
+     */
+    public static final Character[] EMPTY_CHARACTER_OBJECT_ARRAY = new Character[0];
+
+    /**
+     * ArrayUtils instances should NOT be constructed in standard programming.
+     * Instead, the class should be used as ArrayUtils.clone(new int[] {2}).
This constructor is public to permit tools that require a JavaBean instance + * to operate.
+ */ + public ArrayUtils() { + } + + // Basic methods handling multi-dimensional arrays + //----------------------------------------------------------------------- + /** + *Outputs an array as a String, treating null as an empty array.
Multi-dimensional arrays are handled correctly, including + * multi-dimensional primitive arrays.
+ * + *The format is that of Java source code, for example {a,b}.
null
+     * @return a String representation of the array, '{}' if null array input
+     */
+    public static String toString(final Object array) {
+        return toString(array, "{}");
+    }
+
+    /**
+     * Outputs an array as a String handling nulls.
Multi-dimensional arrays are handled correctly, including + * multi-dimensional primitive arrays.
+ * + *The format is that of Java source code, for example {a,b}.
null
+     * @param stringIfNull  the String to return if the array is null
+     * @return a String representation of the array
+     */    
+    public static String toString(final Object array, final String stringIfNull) {
+        if (array == null) {
+            return stringIfNull;
+        }
+        return new ToStringBuilder(array, ToStringStyle.SIMPLE_STYLE).append(array).toString();
+    }
+
+    /**
+     * Get a hashCode for an array handling multi-dimensional arrays correctly.
+ * + *Multi-dimensional primitive arrays are also handled correctly by this method.
+ * + * @param array the array to get a hashCode for, may benull
+     * @return a hashCode for the array, zero if null array input
+     */
+    public static int hashCode(final Object array) {
+        return new HashCodeBuilder().append(array).toHashCode();
+    }
+
+    /**
+     * Compares two arrays, using equals(), handling multi-dimensional arrays + * correctly.
+ * + *Multi-dimensional primitive arrays are also handled correctly by this method.
+ * + * @param array1 the array to get a hashCode for, may benull
+     * @param array2  the array to get a hashCode for, may be null
+     * @return true if the arrays are equal
+     */
+    public static boolean isEquals(final Object array1, final Object array2) {
+        return new EqualsBuilder().append(array1, array2).isEquals();
+    }
+
+    // To map
+    //-----------------------------------------------------------------------
+    /**
+     * Converts the given array into a {@link java.util.Map}. Each element of the array + * must be either a {@link java.util.Map.Entry} or an Array, containing at least two + * elements, where the first element is used as key and the second as + * value.
+ * + *This method can be used to initialize:
+ *
+     * // Create a Map mapping colors.
+     * Map colorMap = MapUtils.toMap(new String[][] {{
+     *     {"RED", "#FF0000"},
+     *     {"GREEN", "#00FF00"},
+     *     {"BLUE", "#0000FF"}});
+     * 
+     * 
+     * This method returns null if null array input.
null
+     * @return a Map that was created from the array
+     * @throws IllegalArgumentException  if one element of this Array is
+     *  itself an Array containing less then two elements
+     * @throws IllegalArgumentException  if the array contains elements other
+     *  than {@link java.util.Map.Entry} and an Array
+     */
+    public static Map toMap(final Object[] array) {
+        if (array == null) {
+            return null;
+        }
+        final Map map = new HashMap((int) (array.length * 1.5));
+        for (int i = 0; i < array.length; i++) {
+            Object object = array[i];
+            if (object instanceof Map.Entry) {
+                Map.Entry entry = (Map.Entry) object;
+                map.put(entry.getKey(), entry.getValue());
+            } else if (object instanceof Object[]) {
+                Object[] entry = (Object[]) object;
+                if (entry.length < 2) {
+                    throw new IllegalArgumentException("Array element " + i + ", '" 
+                        + object
+                        + "', has a length less than 2");
+                }
+                map.put(entry[0], entry[1]);
+            } else {
+                throw new IllegalArgumentException("Array element " + i + ", '" 
+                        + object
+                        + "', is neither of type Map.Entry nor an Array");
+            }
+        }
+        return map;
+    }
+
+    // Clone
+    //-----------------------------------------------------------------------
+    /**
+     * Shallow clones an array returning a typecast result and handling
+     * null.
The objecs in the array are not cloned, thus there is no special + * handling for multi-dimensional arrays.
+ * + *This method returns null if null array input.
null
+     * @return the cloned array, null if null input
+     */
+    public static Object[] clone(final Object[] array) {
+        if (array == null) {
+            return null;
+        }
+        return (Object[]) array.clone();
+    }
+
+    /**
+     * Clones an array returning a typecast result and handling
+     * null.
This method returns null if null array input.
null
+     * @return the cloned array, null if null input
+     */
+    public static long[] clone(final long[] array) {
+        if (array == null) {
+            return null;
+        }
+        return (long[]) array.clone();
+    }
+
+    /**
+     * Clones an array returning a typecast result and handling
+     * null.
This method returns null if null array input.
null
+     * @return the cloned array, null if null input
+     */
+    public static int[] clone(int[] array) {
+        if (array == null) {
+            return null;
+        }
+        return (int[]) array.clone();
+    }
+
+    /**
+     * Clones an array returning a typecast result and handling
+     * null.
This method returns null if null array input.
null
+     * @return the cloned array, null if null input
+     */
+    public static short[] clone(final short[] array) {
+        if (array == null) {
+            return null;
+        }
+        return (short[]) array.clone();
+    }
+
+    /**
+     * Clones an array returning a typecast result and handling
+     * null.
This method returns null if null array input.
null
+     * @return the cloned array, null if null input
+     */
+    public static char[] clone(final char[] array) {
+        if (array == null) {
+            return null;
+        }
+        return (char[]) array.clone();
+    }
+
+    /**
+     * Clones an array returning a typecast result and handling
+     * null.
This method returns null if null array input.
null
+     * @return the cloned array, null if null input
+     */
+    public static byte[] clone(final byte[] array) {
+        if (array == null) {
+            return null;
+        }
+        return (byte[]) array.clone();
+    }
+
+    /**
+     * Clones an array returning a typecast result and handling
+     * null.
This method returns null if null array input.
null
+     * @return the cloned array, null if null input
+     */
+    public static double[] clone(final double[] array) {
+        if (array == null) {
+            return null;
+        }
+        return (double[]) array.clone();
+    }
+
+    /**
+     * Clones an array returning a typecast result and handling
+     * null.
This method returns null if null array input.
null
+     * @return the cloned array, null if null input
+     */
+    public static float[] clone(final float[] array) {
+        if (array == null) {
+            return null;
+        }
+        return (float[]) array.clone();
+    }
+
+    /**
+     * Clones an array returning a typecast result and handling
+     * null.
This method returns null if null array input.
null
+     * @return the cloned array, null if null input
+     */
+    public static boolean[] clone(final boolean[] array) {
+        if (array == null) {
+            return null;
+        }
+        return (boolean[]) array.clone();
+    }
+
+    // Is same length
+    //-----------------------------------------------------------------------
+    /**
+     * Checks whether two arrays are the same length, treating
+     * null arrays as length 0.
+     *
+     * 
Any multi-dimensional aspects of the arrays are ignored.
+ * + * @param array1 the first array, may benull
+     * @param array2 the second array, may be null
+     * @return true if length of arrays matches, treating
+     *  null as an empty array
+     */    
+    public static boolean isSameLength(final Object[] array1, final Object[] array2) {
+        if ((array1 == null && array2 != null && array2.length > 0) ||
+            (array2 == null && array1 != null && array1.length > 0) ||
+            (array1 != null && array2 != null && array1.length != array2.length)) {
+                return false;
+        }
+        return true;
+    }
+
+    /**
+     * Checks whether two arrays are the same length, treating
+     * null arrays as length 0.
null
+     * @param array2 the second array, may be null
+     * @return true if length of arrays matches, treating
+     *  null as an empty array
+     */
+    public static boolean isSameLength(final long[] array1, final long[] array2) {
+        if ((array1 == null && array2 != null && array2.length > 0) ||
+            (array2 == null && array1 != null && array1.length > 0) ||
+            (array1 != null && array2 != null && array1.length != array2.length)) {
+                return false;
+        }
+        return true;
+    }
+
+    /**
+     * Checks whether two arrays are the same length, treating
+     * null arrays as length 0.
null
+     * @param array2 the second array, may be null
+     * @return true if length of arrays matches, treating
+     *  null as an empty array
+     */
+    public static boolean isSameLength(final int[] array1, final int[] array2) {
+        if ((array1 == null && array2 != null && array2.length > 0) ||
+            (array2 == null && array1 != null && array1.length > 0) ||
+            (array1 != null && array2 != null && array1.length != array2.length)) {
+                return false;
+        }
+        return true;
+    }
+
+    /**
+     * Checks whether two arrays are the same length, treating
+     * null arrays as length 0.
null
+     * @param array2 the second array, may be null
+     * @return true if length of arrays matches, treating
+     *  null as an empty array
+     */
+    public static boolean isSameLength(final short[] array1, final short[] array2) {
+        if ((array1 == null && array2 != null && array2.length > 0) ||
+            (array2 == null && array1 != null && array1.length > 0) ||
+            (array1 != null && array2 != null && array1.length != array2.length)) {
+                return false;
+        }
+        return true;
+    }
+
+    /**
+     * Checks whether two arrays are the same length, treating
+     * null arrays as length 0.
null
+     * @param array2 the second array, may be null
+     * @return true if length of arrays matches, treating
+     *  null as an empty array
+     */
+    public static boolean isSameLength(final char[] array1, final char[] array2) {
+        if ((array1 == null && array2 != null && array2.length > 0) ||
+            (array2 == null && array1 != null && array1.length > 0) ||
+            (array1 != null && array2 != null && array1.length != array2.length)) {
+                return false;
+        }
+        return true;
+    }
+
+    /**
+     * Checks whether two arrays are the same length, treating
+     * null arrays as length 0.
null
+     * @param array2 the second array, may be null
+     * @return true if length of arrays matches, treating
+     *  null as an empty array
+     */
+    public static boolean isSameLength(final byte[] array1, final byte[] array2) {
+        if ((array1 == null && array2 != null && array2.length > 0) ||
+            (array2 == null && array1 != null && array1.length > 0) ||
+            (array1 != null && array2 != null && array1.length != array2.length)) {
+                return false;
+        }
+        return true;
+    }
+
+    /**
+     * Checks whether two arrays are the same length, treating
+     * null arrays as length 0.
null
+     * @param array2 the second array, may be null
+     * @return true if length of arrays matches, treating
+     *  null as an empty array
+     */
+    public static boolean isSameLength(final double[] array1, final double[] array2) {
+        if ((array1 == null && array2 != null && array2.length > 0) ||
+            (array2 == null && array1 != null && array1.length > 0) ||
+            (array1 != null && array2 != null && array1.length != array2.length)) {
+                return false;
+        }
+        return true;
+    }
+
+    /**
+     * Checks whether two arrays are the same length, treating
+     * null arrays as length 0.
null
+     * @param array2 the second array, may be null
+     * @return true if length of arrays matches, treating
+     *  null as an empty array
+     */
+    public static boolean isSameLength(final float[] array1, final float[] array2) {
+        if ((array1 == null && array2 != null && array2.length > 0) ||
+            (array2 == null && array1 != null && array1.length > 0) ||
+            (array1 != null && array2 != null && array1.length != array2.length)) {
+                return false;
+        }
+        return true;
+    }
+
+    /**
+     * Checks whether two arrays are the same length, treating
+     * null arrays as length 0.
null
+     * @param array2 the second array, may be null
+     * @return true if length of arrays matches, treating
+     *  null as an empty array
+     */
+    public static boolean isSameLength(final boolean[] array1, final boolean[] array2) {
+        if ((array1 == null && array2 != null && array2.length > 0) ||
+            (array2 == null && array1 != null && array1.length > 0) ||
+            (array1 != null && array2 != null && array1.length != array2.length)) {
+                return false;
+        }
+        return true;
+    }
+
+    /**
+     * Checks whether two arrays are the same type taking into account + * multi-dimensional arrays.
+ * + * @param array1 the first array, must not benull
+     * @param array2 the second array, must not be null
+     * @return true if type of arrays matches
+     * @throws IllegalArgumentException if either array is null
+     */    
+    public static boolean isSameType(final Object array1, final Object array2) {
+        if (array1 == null || array2 == null) {
+            throw new IllegalArgumentException("The Array must not be null");
+        }
+        return array1.getClass().getName().equals(array2.getClass().getName());
+    }
+
+    // Reverse
+    //-----------------------------------------------------------------------
+    /** 
+     * Reverses the order of the given array.
+ * + *There is no special handling for multi-dimensional arrays.
+ * + *This method does nothing if null array input.
null
+     */
+    public static void reverse(final Object[] array) {
+        if (array == null) {
+            return;
+        }
+        int i = 0;
+        int j = array.length - 1;
+        Object tmp;
+        while (j > i) {
+            tmp = array[j];
+            array[j] = array[i];
+            array[i] = tmp;
+            j--;
+            i++;
+        }
+    }
+
+    /**
+     * Reverses the order of the given array.
+ * + *This method does nothing if null array input.
null
+     */
+    public static void reverse(final long[] array) {
+        if (array == null) {
+            return;
+        }
+        int i = 0;
+        int j = array.length - 1;
+        long tmp;
+        while (j > i) {
+            tmp = array[j];
+            array[j] = array[i];
+            array[i] = tmp;
+            j--;
+            i++;
+        }
+    }
+
+    /**
+     * Reverses the order of the given array.
+ * + *This method does nothing if null array input.
null
+     */
+    public static void reverse(final int[] array) {
+        if (array == null) {
+            return;
+        }
+        int i = 0;
+        int j = array.length - 1;
+        int tmp;
+        while (j > i) {
+            tmp = array[j];
+            array[j] = array[i];
+            array[i] = tmp;
+            j--;
+            i++;
+        }
+    }
+
+    /**
+     * Reverses the order of the given array.
+ * + *This method does nothing if null array input.
null
+     */
+    public static void reverse(final short[] array) {
+        if (array == null) {
+            return;
+        }
+        int i = 0;
+        int j = array.length - 1;
+        short tmp;
+        while (j > i) {
+            tmp = array[j];
+            array[j] = array[i];
+            array[i] = tmp;
+            j--;
+            i++;
+        }
+    }
+
+    /**
+     * Reverses the order of the given array.
+ * + *This method does nothing if null array input.
null
+     */
+    public static void reverse(final char[] array) {
+        if (array == null) {
+            return;
+        }
+        int i = 0;
+        int j = array.length - 1;
+        char tmp;
+        while (j > i) {
+            tmp = array[j];
+            array[j] = array[i];
+            array[i] = tmp;
+            j--;
+            i++;
+        }
+    }
+
+    /**
+     * Reverses the order of the given array.
+ * + *This method does nothing if null array input.
null
+     */
+    public static void reverse(final byte[] array) {
+        if (array == null) {
+            return;
+        }
+        int i = 0;
+        int j = array.length - 1;
+        byte tmp;
+        while (j > i) {
+            tmp = array[j];
+            array[j] = array[i];
+            array[i] = tmp;
+            j--;
+            i++;
+        }
+    }
+
+    /**
+     * Reverses the order of the given array.
+ * + *This method does nothing if null array input.
null
+     */
+    public static void reverse(final double[] array) {
+        if (array == null) {
+            return;
+        }
+        int i = 0;
+        int j = array.length - 1;
+        double tmp;
+        while (j > i) {
+            tmp = array[j];
+            array[j] = array[i];
+            array[i] = tmp;
+            j--;
+            i++;
+        }
+    }
+
+    /**
+     * Reverses the order of the given array.
+ * + *This method does nothing if null array input.
null
+     */
+    public static void reverse(final float[] array) {
+        if (array == null) {
+            return;
+        }
+        int i = 0;
+        int j = array.length - 1;
+        float tmp;
+        while (j > i) {
+            tmp = array[j];
+            array[j] = array[i];
+            array[i] = tmp;
+            j--;
+            i++;
+        }
+    }
+
+    /**
+     * Reverses the order of the given array.
+ * + *This method does nothing if null array input.
null
+     */
+    public static void reverse(final boolean[] array) {
+        if (array == null) {
+            return;
+        }
+        int i = 0;
+        int j = array.length - 1;
+        boolean tmp;
+        while (j > i) {
+            tmp = array[j];
+            array[j] = array[i];
+            array[i] = tmp;
+            j--;
+            i++;
+        }
+    }
+
+    // IndexOf search
+    // ----------------------------------------------------------------------
+    
+    // Object IndexOf
+    //-----------------------------------------------------------------------
+    /**
+     * Find the index of the given object in the array.
+ * + *This method returns -1 if null array input.
null
+     * @param objectToFind  the object to find, may be null
+     * @return the index of the object within the array, 
+     *  -1 if not found or null array input
+     */
+    public static int indexOf(final Object[] array, final Object objectToFind) {
+        return indexOf(array, objectToFind, 0);
+    }
+
+    /**
+     * Find the index of the given object in the array starting at the given index.
+ * + *This method returns -1 if null array input.
A negative startIndex is treated as zero. A startIndex larger than the array
+     * length will return -1.
null
+     * @param objectToFind  the object to find, may be null
+     * @param startIndex  the index to start searching at
+     * @return the index of the object within the array starting at the index,
+     *  -1 if not found or null array input
+     */
+    public static int indexOf(final Object[] array, final Object objectToFind, int startIndex) {
+        if (array == null) {
+            return -1;
+        }
+        if (startIndex < 0) {
+            startIndex = 0;
+        }
+        if (objectToFind == null) {
+            for (int i = startIndex; i < array.length; i++) {
+                if (array[i] == null) {
+                    return i;
+                }
+            }
+        } else {
+            for (int i = startIndex; i < array.length; i++) {
+                if (objectToFind.equals(array[i])) {
+                    return i;
+                }
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * Find the last index of the given object within the array.
+ * + *This method returns -1 if null array input.
null
+     * @param objectToFind  the object to find, may be null
+     * @return the last index of the object within the array,
+     *  -1 if not found or null array input
+     */
+    public static int lastIndexOf(final Object[] array, final Object objectToFind) {
+        return lastIndexOf(array, objectToFind, Integer.MAX_VALUE);
+    }
+
+    /**
+     * Find the last index of the given object in the array starting at the given index.
+ * + *This method returns -1 if null array input.
A negative startIndex will return -1. A startIndex larger than
+     * the array length will search from the end of the array.
null
+     * @param objectToFind  the object to find, may be null
+     * @param startIndex  the start index to travers backwards from
+     * @return the last index of the object within the array,
+     *  -1 if not found or null array input
+     */
+    public static int lastIndexOf(final Object[] array, final Object objectToFind, int startIndex) {
+        if (array == null) {
+            return -1;
+        }
+        if (startIndex < 0) {
+            return -1;
+        } else if (startIndex >= array.length) {
+            startIndex = array.length - 1;
+        }
+        if (objectToFind == null) {
+            for (int i = startIndex; i >= 0; i--) {
+                if (array[i] == null) {
+                    return i;
+                }
+            }
+        } else {
+            for (int i = startIndex; i >= 0; i--) {
+                if (objectToFind.equals(array[i])) {
+                    return i;
+                }
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * Checks if the object is in the given array.
+ * + *The method returns false if a null array is passed in.
true if the array contains the object
+     */
+    public static boolean contains(final Object[] array, final Object objectToFind) {
+        return (indexOf(array, objectToFind) != -1);
+    }
+
+    // long IndexOf
+    //-----------------------------------------------------------------------
+    /**
+     * Find the index of the given value in the array.
+ * + *This method returns -1 if null array input.
null
+     * @param valueToFind  the value to find
+     * @return the index of the value within the array,
+     *  -1 if not found or null array input
+     */
+    public static int indexOf(final long[] array, final long valueToFind) {
+        return indexOf(array, valueToFind, 0);
+    }
+
+    /**
+     * Find the index of the given value in the array starting at the given index.
+ * + *This method returns -1 if null array input.
A negative startIndex is treated as zero. A startIndex larger than the array + * length will return -1.
+ * + * @param array the array to search through for the object, may benull
+     * @param valueToFind  the value to find
+     * @param startIndex  the index to start searching at
+     * @return the index of the value within the array,
+     *  -1 if not found or null array input
+     */
+    public static int indexOf(final long[] array, final long valueToFind, int startIndex) {
+        if (array == null) {
+            return -1;
+        }
+        if (startIndex < 0) {
+            startIndex = 0;
+        }
+        for (int i = startIndex; i < array.length; i++) {
+            if (valueToFind == array[i]) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * Find the last index of the given value within the array.
+ * + *This method returns -1 if null array input.
null
+     * @param valueToFind  the object to find
+     * @return the last index of the value within the array,
+     *  -1 if not found or null array input
+     */
+    public static int lastIndexOf(final long[] array, final long valueToFind) {
+        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
+    }
+
+    /**
+     * Find the last index of the given value in the array starting at the given index.
+ * + *This method returns -1 if null array input.
A negative startIndex will return -1. A startIndex larger than the array + * length will search from the end of the array.
+ * + * @param array the array to traverse for looking for the object, may benull
+     * @param valueToFind  the value to find
+     * @param startIndex  the start index to travers backwards from
+     * @return the last index of the value within the array,
+     *  -1 if not found or null array input
+     */
+    public static int lastIndexOf(final long[] array, final long valueToFind, int startIndex) {
+        if (array == null) {
+            return -1;
+        }
+        if (startIndex < 0) {
+            return -1;
+        } else if (startIndex >= array.length) {
+            startIndex = array.length - 1;
+        }
+        for (int i = startIndex; i >= 0; i--) {
+            if (valueToFind == array[i]) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * Checks if the value is in the given array.
+ * + *The method returns false if a null array is passed in.
true if the array contains the object
+     */
+    public static boolean contains(final long[] array, final long valueToFind) {
+        return (indexOf(array, valueToFind) != -1);
+    }
+
+    // int IndexOf
+    //-----------------------------------------------------------------------
+    /**
+     * Find the index of the given value in the array.
+ * + *This method returns -1 if null array input.
null
+     * @param valueToFind  the value to find
+     * @return the index of the value within the array,
+     *  -1 if not found or null array input
+     */
+    public static int indexOf(final int[] array, final int valueToFind) {
+        return indexOf(array, valueToFind, 0);
+    }
+
+    /**
+     * Find the index of the given value in the array starting at the given index.
+ * + *This method returns -1 if null array input.
A negative startIndex is treated as zero. A startIndex larger than the array + * length will return -1.
+ * + * @param array the array to search through for the object, may benull
+     * @param valueToFind  the value to find
+     * @param startIndex  the index to start searching at
+     * @return the index of the value within the array,
+     *  -1 if not found or null array input
+     */
+    public static int indexOf(final int[] array, final int valueToFind, int startIndex) {
+        if (array == null) {
+            return -1;
+        }
+        if (startIndex < 0) {
+            startIndex = 0;
+        }
+        for (int i = startIndex; i < array.length; i++) {
+            if (valueToFind == array[i]) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * Find the last index of the given value within the array.
+ * + *This method returns -1 if null array input.
null
+     * @param valueToFind  the object to find
+     * @return the last index of the value within the array,
+     *  -1 if not found or null array input
+     */
+    public static int lastIndexOf(final int[] array, final int valueToFind) {
+        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
+    }
+
+    /**
+     * Find the last index of the given value in the array starting at the given index.
+ * + *This method returns -1 if null array input.
A negative startIndex will return -1. A startIndex larger than the array + * length will search from the end of the array.
+ * + * @param array the array to traverse for looking for the object, may benull
+     * @param valueToFind  the value to find
+     * @param startIndex  the start index to travers backwards from
+     * @return the last index of the value within the array,
+     *  -1 if not found or null array input
+     */
+    public static int lastIndexOf(final int[] array, final int valueToFind, int startIndex) {
+        if (array == null) {
+            return -1;
+        }
+        if (startIndex < 0) {
+            return -1;
+        } else if (startIndex >= array.length) {
+            startIndex = array.length - 1;
+        }
+        for (int i = startIndex; i >= 0; i--) {
+            if (valueToFind == array[i]) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * Checks if the value is in the given array.
+ * + *The method returns false if a null array is passed in.
true if the array contains the object
+     */
+    public static boolean contains(final int[] array, final int valueToFind) {
+        return (indexOf(array, valueToFind) != -1);
+    }
+
+    // short IndexOf
+    //-----------------------------------------------------------------------
+    /**
+     * Find the index of the given value in the array.
+ * + *This method returns -1 if null array input.
null
+     * @param valueToFind  the value to find
+     * @return the index of the value within the array,
+     *  -1 if not found or null array input
+     */
+    public static int indexOf(final short[] array, final short valueToFind) {
+        return indexOf(array, valueToFind, 0);
+    }
+
+    /**
+     * Find the index of the given value in the array starting at the given index.
+ * + *This method returns -1 if null array input.
A negative startIndex is treated as zero. A startIndex larger than the array + * length will return -1.
+ * + * @param array the array to search through for the object, may benull
+     * @param valueToFind  the value to find
+     * @param startIndex  the index to start searching at
+     * @return the index of the value within the array,
+     *  -1 if not found or null array input
+     */
+    public static int indexOf(final short[] array, final short valueToFind, int startIndex) {
+        if (array == null) {
+            return -1;
+        }
+        if (startIndex < 0) {
+            startIndex = 0;
+        }
+        for (int i = startIndex; i < array.length; i++) {
+            if (valueToFind == array[i]) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * Find the last index of the given value within the array.
+ * + *This method returns -1 if null array input.
null
+     * @param valueToFind  the object to find
+     * @return the last index of the value within the array,
+     *  -1 if not found or null array input
+     */
+    public static int lastIndexOf(final short[] array, final short valueToFind) {
+        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
+    }
+
+    /**
+     * Find the last index of the given value in the array starting at the given index.
+ * + *This method returns -1 if null array input.
A negative startIndex will return -1. A startIndex larger than the array + * length will search from the end of the array.
+ * + * @param array the array to traverse for looking for the object, may benull
+     * @param valueToFind  the value to find
+     * @param startIndex  the start index to travers backwards from
+     * @return the last index of the value within the array,
+     *  -1 if not found or null array input
+     */
+    public static int lastIndexOf(final short[] array, final short valueToFind, int startIndex) {
+        if (array == null) {
+            return -1;
+        }
+        if (startIndex < 0) {
+            return -1;
+        } else if (startIndex >= array.length) {
+            startIndex = array.length - 1;
+        }
+        for (int i = startIndex; i >= 0; i--) {
+            if (valueToFind == array[i]) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * Checks if the value is in the given array.
+ * + *The method returns false if a null array is passed in.
true if the array contains the object
+     */
+    public static boolean contains(final short[] array, final short valueToFind) {
+        return (indexOf(array, valueToFind) != -1);
+    }
+
+    // byte IndexOf
+    //-----------------------------------------------------------------------
+    /**
+     * Find the index of the given value in the array.
+ * + *This method returns -1 if null array input.
null
+     * @param valueToFind  the value to find
+     * @return the index of the value within the array,
+     *  -1 if not found or null array input
+     */
+    public static int indexOf(final byte[] array, final byte valueToFind) {
+        return indexOf(array, valueToFind, 0);
+    }
+
+    /**
+     * Find the index of the given value in the array starting at the given index.
+ * + *This method returns -1 if null array input.
A negative startIndex is treated as zero. A startIndex larger than the array + * length will return -1.
+ * + * @param array the array to search through for the object, may benull
+     * @param valueToFind  the value to find
+     * @param startIndex  the index to start searching at
+     * @return the index of the value within the array,
+     *  -1 if not found or null array input
+     */
+    public static int indexOf(final byte[] array, final byte valueToFind, int startIndex) {
+        if (array == null) {
+            return -1;
+        }
+        if (startIndex < 0) {
+            startIndex = 0;
+        }
+        for (int i = startIndex; i < array.length; i++) {
+            if (valueToFind == array[i]) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * Find the last index of the given value within the array.
+ * + *This method returns -1 if null array input.
null
+     * @param valueToFind  the object to find
+     * @return the last index of the value within the array,
+     *  -1 if not found or null array input
+     */
+    public static int lastIndexOf(final byte[] array, final byte valueToFind) {
+        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
+    }
+
+    /**
+     * Find the last index of the given value in the array starting at the given index.
+ * + *This method returns -1 if null array input.
A negative startIndex will return -1. A startIndex larger than the array + * length will search from the end of the array.
+ * + * @param array the array to traverse for looking for the object, may benull
+     * @param valueToFind  the value to find
+     * @param startIndex  the start index to travers backwards from
+     * @return the last index of the value within the array,
+     *  -1 if not found or null array input
+     */
+    public static int lastIndexOf(final byte[] array, final byte valueToFind, int startIndex) {
+        if (array == null) {
+            return -1;
+        }
+        if (startIndex < 0) {
+            return -1;
+        } else if (startIndex >= array.length) {
+            startIndex = array.length - 1;
+        }
+        for (int i = startIndex; i >= 0; i--) {
+            if (valueToFind == array[i]) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * Checks if the value is in the given array.
+ * + *The method returns false if a null array is passed in.
true if the array contains the object
+     */
+    public static boolean contains(final byte[] array, final byte valueToFind) {
+        return (indexOf(array, valueToFind) != -1);
+    }
+
+    // double IndexOf
+    //-----------------------------------------------------------------------
+    /**
+     * Find the index of the given value in the array.
+ * + *This method returns -1 if null array input.
null
+     * @param valueToFind  the value to find
+     * @return the index of the value within the array,
+     *  -1 if not found or null array input
+     */
+    public static int indexOf(final double[] array, final double valueToFind) {
+        return indexOf(array, valueToFind, 0);
+    }
+
+    /**
+     * Find the index of the given value within a given tolerance in the array. + * This method will return the index of the first value which falls between the region + * defined by valueToFind - tolerance and valueToFind + tolerance.
+ * + *This method returns -1 if null array input.
null
+     * @param valueToFind  the value to find
+     * @param tolerance tolerance of the search
+     * @return the index of the value within the array,
+     *  -1 if not found or null array input
+     */
+    public static int indexOf(final double[] array, final double valueToFind, final double tolerance) {
+        return indexOf(array, valueToFind, 0, tolerance);
+    }
+
+    /**
+     * Find the index of the given value in the array starting at the given index.
+ * + *This method returns -1 if null array input.
A negative startIndex is treated as zero. A startIndex larger than the array + * length will return -1.
+ * + * @param array the array to search through for the object, may benull
+     * @param valueToFind  the value to find
+     * @param startIndex  the index to start searching at
+     * @return the index of the value within the array,
+     *  -1 if not found or null array input
+     */
+    public static int indexOf(final double[] array, final double valueToFind, int startIndex) {
+        if (array == null || array.length == 0) {
+            return -1;
+        }
+        if (startIndex < 0) {
+            startIndex = 0;
+        }
+        for (int i = startIndex; i < array.length; i++) {
+            if (valueToFind == array[i]) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * Find the index of the given value in the array starting at the given index. + * This method will return the index of the first value which falls between the region + * defined by valueToFind - tolerance and valueToFind + tolerance.
+ * + *This method returns -1 if null array input.
A negative startIndex is treated as zero. A startIndex larger than the array + * length will return -1.
+ * + * @param array the array to search through for the object, may benull
+     * @param valueToFind  the value to find
+     * @param startIndex  the index to start searching at
+     * @param tolerance tolerance of the search
+     * @return the index of the value within the array,
+     *  -1 if not found or null array input
+     */
+    public static int indexOf(final double[] array, final double valueToFind, int startIndex, double tolerance) {
+        if (array == null || array.length == 0) {
+            return -1;
+        }
+        if (startIndex < 0) {
+            startIndex = 0;
+        }
+        double min = valueToFind - tolerance;
+        double max = valueToFind + tolerance;
+        for (int i = startIndex; i < array.length; i++) {
+            if (array[i] >= min && array[i] <= max) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * Find the last index of the given value within the array.
+ * + *This method returns -1 if null array input.
null
+     * @param valueToFind  the object to find
+     * @return the last index of the value within the array,
+     *  -1 if not found or null array input
+     */
+    public static int lastIndexOf(final double[] array, final double valueToFind) {
+        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
+    }
+
+    /**
+     * Find the last index of the given value within a given tolerance in the array. + * This method will return the index of the last value which falls between the region + * defined by valueToFind - tolerance and valueToFind + tolerance.
+ * + *This method returns -1 if null array input.
null
+     * @param valueToFind  the value to find
+     * @param tolerance tolerance of the search
+     * @return the index of the value within the array,
+     *  -1 if not found or null array input
+     */
+    public static int lastIndexOf(final double[] array, final double valueToFind, final double tolerance) {
+        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE, tolerance);
+    }
+
+    /**
+     * Find the last index of the given value in the array starting at the given index.
+ * + *This method returns -1 if null array input.
A negative startIndex will return -1. A startIndex larger than the array + * length will search from the end of the array.
+ * + * @param array the array to traverse for looking for the object, may benull
+     * @param valueToFind  the value to find
+     * @param startIndex  the start index to travers backwards from
+     * @return the last index of the value within the array,
+     *  -1 if not found or null array input
+     */
+    public static int lastIndexOf(final double[] array, final double valueToFind, int startIndex) {
+        if (array == null || array.length == 0) {
+            return -1;
+        }
+        if (startIndex < 0) {
+            return -1;
+        } else if (startIndex >= array.length) {
+            startIndex = array.length - 1;
+        }
+        for (int i = startIndex; i >= 0; i--) {
+            if (valueToFind == array[i]) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * Find the last index of the given value in the array starting at the given index. + * This method will return the index of the last value which falls between the region + * defined by valueToFind - tolerance and valueToFind + tolerance.
+ * + *This method returns -1 if null array input.
A negative startIndex will return -1. A startIndex larger than the array + * length will search from the end of the array.
+ * + * @param array the array to traverse for looking for the object, may benull
+     * @param valueToFind  the value to find
+     * @param startIndex  the start index to travers backwards from
+     * @param tolerance  search for value within plus/minus this amount
+     * @return the last index of the value within the array,
+     *  -1 if not found or null array input
+     */
+    public static int lastIndexOf(final double[] array, final double valueToFind, int startIndex, double tolerance) {
+        if (array == null || array.length == 0) {
+            return -1;
+        }
+        if (startIndex < 0) {
+            return -1;
+        } else if (startIndex >= array.length) {
+            startIndex = array.length - 1;
+        }
+        double min = valueToFind - tolerance;
+        double max = valueToFind + tolerance;
+        for (int i = startIndex; i >= 0; i--) {
+            if (array[i] >= min && array[i] <= max) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * Checks if the value is in the given array.
+ * + *The method returns false if a null array is passed in.
true if the array contains the object
+     */
+    public static boolean contains(final double[] array, final double valueToFind) {
+        return (indexOf(array, valueToFind) != -1);
+    }
+
+    /**
+     * Checks if a value falling within the given tolerance is in the + * given array. If the array contains a value within the inclusive range + * defined by (value - tolerance) to (value + tolerance).
+ * + *The method returns false if a null array
+     * is passed in.
Find the index of the given value in the array.
+ * + *This method returns -1 if null array input.
null
+     * @param valueToFind  the value to find
+     * @return the index of the value within the array,
+     *  -1 if not found or null array input
+     */
+    public static int indexOf(final float[] array, final float valueToFind) {
+        return indexOf(array, valueToFind, 0);
+    }
+
+    /**
+     * Find the index of the given value in the array starting at the given index.
+ * + *This method returns -1 if null array input.
A negative startIndex is treated as zero. A startIndex larger than the array + * length will return -1.
+ * + * @param array the array to search through for the object, may benull
+     * @param valueToFind  the value to find
+     * @param startIndex  the index to start searching at
+     * @return the index of the value within the array,
+     *  -1 if not found or null array input
+     */
+    public static int indexOf(final float[] array, final float valueToFind, int startIndex) {
+        if (array == null || array.length == 0) {
+            return -1;
+        }
+        if (startIndex < 0) {
+            startIndex = 0;
+        }
+        for (int i = startIndex; i < array.length; i++) {
+            if (valueToFind == array[i]) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * Find the last index of the given value within the array.
+ * + *This method returns -1 if null array input.
null
+     * @param valueToFind  the object to find
+     * @return the last index of the value within the array,
+     *  -1 if not found or null array input
+     */
+    public static int lastIndexOf(final float[] array, final float valueToFind) {
+        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
+    }
+
+    /**
+     * Find the last index of the given value in the array starting at the given index.
+ * + *This method returns -1 if null array input.
A negative startIndex will return -1. A startIndex larger than the array + * length will search from the end of the array.
+ * + * @param array the array to traverse for looking for the object, may benull
+     * @param valueToFind  the value to find
+     * @param startIndex  the start index to travers backwards from
+     * @return the last index of the value within the array,
+     *  -1 if not found or null array input
+     */
+    public static int lastIndexOf(final float[] array, final float valueToFind, int startIndex) {
+        if (array == null || array.length == 0) {
+            return -1;
+        }
+        if (startIndex < 0) {
+            return -1;
+        } else if (startIndex >= array.length) {
+            startIndex = array.length - 1;
+        }
+        for (int i = startIndex; i >= 0; i--) {
+            if (valueToFind == array[i]) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * Checks if the value is in the given array.
+ * + *The method returns false if a null array is passed in.
true if the array contains the object
+     */
+    public static boolean contains(final float[] array, final float valueToFind) {
+        return (indexOf(array, valueToFind) != -1);
+    }
+
+    // boolean IndexOf
+    //-----------------------------------------------------------------------
+    /**
+     * Find the index of the given value in the array.
+ * + *This method returns -1 if null array input.
null
+     * @param valueToFind  the value to find
+     * @return the index of the value within the array,
+     *  -1 if not found or null array input
+     */
+    public static int indexOf(final boolean[] array, final boolean valueToFind) {
+        return indexOf(array, valueToFind, 0);
+    }
+
+    /**
+     * Find the index of the given value in the array starting at the given index.
+ * + *This method returns -1 if null array input.
A negative startIndex is treated as zero. A startIndex larger than the array + * length will return -1.
+ * + * @param array the array to search through for the object, may benull
+     * @param valueToFind  the value to find
+     * @param startIndex  the index to start searching at
+     * @return the index of the value within the array,
+     *  -1 if not found or null array input
+     */
+    public static int indexOf(final boolean[] array, final boolean valueToFind, int startIndex) {
+        if (array == null || array.length == 0) {
+            return -1;
+        }
+        if (startIndex < 0) {
+            startIndex = 0;
+        }
+        for (int i = startIndex; i < array.length; i++) {
+            if (valueToFind == array[i]) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * Find the last index of the given value within the array.
+ * + *This method returns -1 if null array input.
null
+     * @param valueToFind  the object to find
+     * @return the last index of the value within the array,
+     *  -1 if not found or null array input
+     */
+    public static int lastIndexOf(final boolean[] array, final boolean valueToFind) {
+        return lastIndexOf(array, valueToFind, Integer.MAX_VALUE);
+    }
+
+    /**
+     * Find the last index of the given value in the array starting at the given index.
+ * + *This method returns -1 if null array input.
A negative startIndex will return -1. A startIndex larger than the array + * length will search from the end of the array.
+ * + * @param array the array to traverse for looking for the object, may benull
+     * @param valueToFind  the value to find
+     * @param startIndex  the start index to travers backwards from
+     * @return the last index of the value within the array,
+     *  -1 if not found or null array input
+     */
+    public static int lastIndexOf(final boolean[] array, final boolean valueToFind, int startIndex) {
+        if (array == null || array.length == 0) {
+            return -1;
+        }
+        if (startIndex < 0) {
+            return -1;
+        } else if (startIndex >= array.length) {
+            startIndex = array.length - 1;
+        }
+        for (int i = startIndex; i >= 0; i--) {
+            if (valueToFind == array[i]) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * Checks if the value is in the given array.
+ * + *The method returns false if a null array is passed in.
true if the array contains the object
+     */
+    public static boolean contains(final boolean[] array, final boolean valueToFind) {
+        return (indexOf(array, valueToFind) != -1);
+    }
+
+    // Primitive/Object array converters
+    // ----------------------------------------------------------------------
+    
+    // Long array converters
+    // ----------------------------------------------------------------------
+    /**
+     * Converts an array of object Longs to primitives.
+ * + *This method returns null if null array input.
Long array, may be null
+     * @return a long array, null if null array input
+     * @throws NullPointerException if array content is null
+     */
+    public static long[] toPrimitive(final Long[] array) {
+        if (array == null) {
+            return null;
+        } else if (array.length == 0) {
+            return EMPTY_LONG_ARRAY;
+        }
+        final long[] result = new long[array.length];
+        for (int i = 0; i < array.length; i++) {
+            result[i] = array[i].longValue();
+        }
+        return result;
+    }
+    
+    /**
+     * Converts an array of object Long to primitives handling null.
This method returns null if null array input.
Long array, may be null
+     * @param valueForNull  the value to insert if null found
+     * @return a long array, null if null array input
+     */
+    public static long[] toPrimitive(final Long[] array, final long valueForNull) {
+        if (array == null) {
+            return null;
+        } else if (array.length == 0) {
+            return EMPTY_LONG_ARRAY;
+        }
+        final long[] result = new long[array.length];
+        for (int i = 0; i < array.length; i++) {
+            Long b = array[i];
+            result[i] = (b == null ? valueForNull : b.longValue());
+        }
+        return result;
+    }
+    
+    /**
+     * Converts an array of primitive longs to objects.
+ * + *This method returns null if null array input.
long array
+     * @return a Long array, null if null array input
+     */
+    public static Long[] toObject(final long[] array) {
+        if (array == null) {
+            return null;
+        } else if (array.length == 0) {
+            return EMPTY_LONG_OBJECT_ARRAY;
+        }
+        final Long[] result = new Long[array.length];
+        for (int i = 0; i < array.length; i++) {
+            result[i] = new Long(array[i]);
+        }
+        return result;
+    }
+
+    // Int array converters
+    // ----------------------------------------------------------------------
+    /**
+     * Converts an array of object Integers to primitives.
+ * + *This method returns null if null array input.
Integer array, may be null
+     * @return an int array, null if null array input
+     * @throws NullPointerException if array content is null
+     */
+    public static int[] toPrimitive(final Integer[] array) {
+        if (array == null) {
+            return null;
+        } else if (array.length == 0) {
+            return EMPTY_INT_ARRAY;
+        }
+        final int[] result = new int[array.length];
+        for (int i = 0; i < array.length; i++) {
+            result[i] = array[i].intValue();
+        }
+        return result;
+    }
+
+    /**
+     * Converts an array of object Integer to primitives handling null.
This method returns null if null array input.
Integer array, may be null
+     * @param valueForNull  the value to insert if null found
+     * @return an int array, null if null array input
+     */
+    public static int[] toPrimitive(final Integer[] array, final int valueForNull) {
+        if (array == null) {
+            return null;
+        } else if (array.length == 0) {
+            return EMPTY_INT_ARRAY;
+        }
+        final int[] result = new int[array.length];
+        for (int i = 0; i < array.length; i++) {
+            Integer b = array[i];
+            result[i] = (b == null ? valueForNull : b.intValue());
+        }
+        return result;
+    }
+
+    /**
+     * Converts an array of primitive ints to objects.
+ * + *This method returns null if null array input.
int array
+     * @return an Integer array, null if null array input
+     */
+    public static Integer[] toObject(final int[] array) {
+        if (array == null) {
+            return null;
+        } else if (array.length == 0) {
+            return EMPTY_INTEGER_OBJECT_ARRAY;
+        }
+        final Integer[] result = new Integer[array.length];
+        for (int i = 0; i < array.length; i++) {
+            result[i] = new Integer(array[i]);
+        }
+        return result;
+    }
+    
+    // Short array converters
+    // ----------------------------------------------------------------------
+    /**
+     * Converts an array of object Shorts to primitives.
+ * + *This method returns null if null array input.
Short array, may be null
+     * @return a byte array, null if null array input
+     * @throws NullPointerException if array content is null
+     */
+    public static short[] toPrimitive(final Short[] array) {
+        if (array == null) {
+            return null;
+        } else if (array.length == 0) {
+            return EMPTY_SHORT_ARRAY;
+        }
+        final short[] result = new short[array.length];
+        for (int i = 0; i < array.length; i++) {
+            result[i] = array[i].shortValue();
+        }
+        return result;
+    }
+
+    /**
+     * Converts an array of object Short to primitives handling null.
This method returns null if null array input.
Short array, may be null
+     * @param valueForNull  the value to insert if null found
+     * @return a byte array, null if null array input
+     */
+    public static short[] toPrimitive(final Short[] array, final short valueForNull) {
+        if (array == null) {
+            return null;
+        } else if (array.length == 0) {
+            return EMPTY_SHORT_ARRAY;
+        }
+        final short[] result = new short[array.length];
+        for (int i = 0; i < array.length; i++) {
+            Short b = array[i];
+            result[i] = (b == null ? valueForNull : b.shortValue());
+        }
+        return result;
+    }
+
+    /**
+     * Converts an array of primitive shorts to objects.
+ * + *This method returns null if null array input.
short array
+     * @return a Short array, null if null array input
+     */
+    public static Short[] toObject(final short[] array) {
+        if (array == null) {
+            return null;
+        } else if (array.length == 0) {
+            return EMPTY_SHORT_OBJECT_ARRAY;
+        }
+        final Short[] result = new Short[array.length];
+        for (int i = 0; i < array.length; i++) {
+            result[i] = new Short(array[i]);
+        }
+        return result;
+    }    
+
+    // Byte array converters
+    // ----------------------------------------------------------------------
+    /**
+     * Converts an array of object Bytes to primitives.
+ * + *This method returns null if null array input.
Byte array, may be null
+     * @return a byte array, null if null array input
+     * @throws NullPointerException if array content is null
+     */
+    public static byte[] toPrimitive(final Byte[] array) {
+        if (array == null) {
+            return null;
+        } else if (array.length == 0) {
+            return EMPTY_BYTE_ARRAY;
+        }
+        final byte[] result = new byte[array.length];
+        for (int i = 0; i < array.length; i++) {
+            result[i] = array[i].byteValue();
+        }
+        return result;
+    }
+
+    /**
+     * Converts an array of object Bytes to primitives handling null.
This method returns null if null array input.
Byte array, may be null
+     * @param valueForNull  the value to insert if null found
+     * @return a byte array, null if null array input
+     */
+    public static byte[] toPrimitive(final Byte[] array, final byte valueForNull) {
+        if (array == null) {
+            return null;
+        } else if (array.length == 0) {
+            return EMPTY_BYTE_ARRAY;
+        }
+        final byte[] result = new byte[array.length];
+        for (int i = 0; i < array.length; i++) {
+            Byte b = array[i];
+            result[i] = (b == null ? valueForNull : b.byteValue());
+        }
+        return result;
+    }
+
+    /**
+     * Converts an array of primitive bytes to objects.
+ * + *This method returns null if null array input.
byte array
+     * @return a Byte array, null if null array input
+     */
+    public static Byte[] toObject(final byte[] array) {
+        if (array == null) {
+            return null;
+        } else if (array.length == 0) {
+            return EMPTY_BYTE_OBJECT_ARRAY;
+        }
+        final Byte[] result = new Byte[array.length];
+        for (int i = 0; i < array.length; i++) {
+            result[i] = new Byte(array[i]);
+        }
+        return result;
+    }  
+    
+    // Double array converters
+    // ----------------------------------------------------------------------
+    /**
+     * Converts an array of object Doubles to primitives.
+ * + *This method returns null if null array input.
Double array, may be null
+     * @return a double array, null if null array input
+     * @throws NullPointerException if array content is null
+     */
+    public static double[] toPrimitive(final Double[] array) {
+        if (array == null) {
+            return null;
+        } else if (array.length == 0) {
+            return EMPTY_DOUBLE_ARRAY;
+        }
+        final double[] result = new double[array.length];
+        for (int i = 0; i < array.length; i++) {
+            result[i] = array[i].doubleValue();
+        }
+        return result;
+    }
+
+    /**
+     * Converts an array of object Doubles to primitives handling null.
This method returns null if null array input.
Double array, may be null
+     * @param valueForNull  the value to insert if null found
+     * @return a double array, null if null array input
+     */
+    public static double[] toPrimitive(final Double[] array, final double valueForNull) {
+        if (array == null) {
+            return null;
+        } else if (array.length == 0) {
+            return EMPTY_DOUBLE_ARRAY;
+        }
+        final double[] result = new double[array.length];
+        for (int i = 0; i < array.length; i++) {
+            Double b = array[i];
+            result[i] = (b == null ? valueForNull : b.doubleValue());
+        }
+        return result;
+    }
+
+    /**
+     * Converts an array of primitive doubles to objects.
+ * + *This method returns null if null array input.
double array
+     * @return a Double array, null if null array input
+     */
+    public static Double[] toObject(final double[] array) {
+        if (array == null) {
+            return null;
+        } else if (array.length == 0) {
+            return EMPTY_DOUBLE_OBJECT_ARRAY;
+        }
+        final Double[] result = new Double[array.length];
+        for (int i = 0; i < array.length; i++) {
+            result[i] = new Double(array[i]);
+        }
+        return result;
+    }
+
+    //   Float array converters
+    // ----------------------------------------------------------------------
+    /**
+     * Converts an array of object Floats to primitives.
+ * + *This method returns null if null array input.
Float array, may be null
+     * @return a float array, null if null array input
+     * @throws NullPointerException if array content is null
+     */
+    public static float[] toPrimitive(final Float[] array) {
+        if (array == null) {
+            return null;
+        } else if (array.length == 0) {
+            return EMPTY_FLOAT_ARRAY;
+        }
+        final float[] result = new float[array.length];
+        for (int i = 0; i < array.length; i++) {
+            result[i] = array[i].floatValue();
+        }
+        return result;
+    }
+
+    /**
+     * Converts an array of object Floats to primitives handling null.
This method returns null if null array input.
Float array, may be null
+     * @param valueForNull  the value to insert if null found
+     * @return a float array, null if null array input
+     */
+    public static float[] toPrimitive(final Float[] array, final float valueForNull) {
+        if (array == null) {
+            return null;
+        } else if (array.length == 0) {
+            return EMPTY_FLOAT_ARRAY;
+        }
+        final float[] result = new float[array.length];
+        for (int i = 0; i < array.length; i++) {
+            Float b = array[i];
+            result[i] = (b == null ? valueForNull : b.floatValue());
+        }
+        return result;
+    }
+
+    /**
+     * Converts an array of primitive floats to objects.
+ * + *This method returns null if null array input.
float array
+     * @return a Float array, null if null array input
+     */
+    public static Float[] toObject(final float[] array) {
+        if (array == null) {
+            return null;
+        } else if (array.length == 0) {
+            return EMPTY_FLOAT_OBJECT_ARRAY;
+        }
+        final Float[] result = new Float[array.length];
+        for (int i = 0; i < array.length; i++) {
+            result[i] = new Float(array[i]);
+        }
+        return result;
+    }
+
+    // Boolean array converters
+    // ----------------------------------------------------------------------
+    /**
+     * Converts an array of object Booleans to primitives.
+ * + *This method returns null if null array input.
Boolean array, may be null
+     * @return a boolean array, null if null array input
+     * @throws NullPointerException if array content is null
+     */
+    public static boolean[] toPrimitive(final Boolean[] array) {
+        if (array == null) {
+            return null;
+        } else if (array.length == 0) {
+            return EMPTY_BOOLEAN_ARRAY;
+        }
+        final boolean[] result = new boolean[array.length];
+        for (int i = 0; i < array.length; i++) {
+            result[i] = array[i].booleanValue();
+        }
+        return result;
+    }
+
+    /**
+     * Converts an array of object Booleans to primitives handling null.
This method returns null if null array input.
Boolean array, may be null
+     * @param valueForNull  the value to insert if null found
+     * @return a boolean array, null if null array input
+     */
+    public static boolean[] toPrimitive(final Boolean[] array, final boolean valueForNull) {
+        if (array == null) {
+            return null;
+        } else if (array.length == 0) {
+            return EMPTY_BOOLEAN_ARRAY;
+        }
+        final boolean[] result = new boolean[array.length];
+        for (int i = 0; i < array.length; i++) {
+            Boolean b = array[i];
+            result[i] = (b == null ? valueForNull : b.booleanValue());
+        }
+        return result;
+    }
+
+    /**
+     * Converts an array of primitive booleans to objects.
+ * + *This method returns null if null array input.
boolean array
+     * @return a Boolean array, null if null array input
+     */
+    public static Boolean[] toObject(final boolean[] array) {
+        if (array == null) {
+            return null;
+        } else if (array.length == 0) {
+            return EMPTY_BOOLEAN_OBJECT_ARRAY;
+        }
+        final Boolean[] result = new Boolean[array.length];
+        for (int i = 0; i < array.length; i++) {
+            result[i] = (array[i] ? Boolean.TRUE : Boolean.FALSE);
+        }
+        return result;
+    }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/BitField.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/BitField.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/BitField.java	30 Aug 2012 16:24:42 -0000	1.1
@@ -0,0 +1,327 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ * Operations on bit-mapped fields.
+ * + * @author Apache Jakarta POI + * @author Scott Sanders (sanders at apache dot org) + * @author Marc Johnson (mjohnson at apache dot org) + * @author Andrew C. Oliver (acoliver at apache dot org) + * @author Stephen Colebourne + * @author Pete Gieser + * @author Gary Gregory + * @since 2.0 + * @version $Id: BitField.java,v 1.1 2012/08/30 16:24:42 marcin Exp $ + */ +public class BitField { + + private final int _mask; + private final int _shift_count; + + /** + *Creates a BitField instance.
+ * + * @param mask the mask specifying which bits apply to this + * BitField. Bits that are set in this mask are the bits + * that this BitField operates on + */ + public BitField(final int mask) { + _mask = mask; + int count = 0; + int bit_pattern = mask; + + if (bit_pattern != 0) { + while ((bit_pattern & 1) == 0) { + count++; + bit_pattern >>= 1; + } + } + _shift_count = count; + } + + /** + *Obtains the value for the specified BitField, appropriately + * shifted right.
+ * + *Many users of a BitField will want to treat the specified + * bits as an int value, and will not want to be aware that the + * value is stored as a BitField (and so shifted left so many + * bits).
+ * + * @see #setValue + * @param holder the int data containing the bits we're interested + * in + * @return the selected bits, shifted right appropriately + */ + public int getValue(final int holder) { + return getRawValue(holder) >> _shift_count; + } + + /** + *Obtains the value for the specified BitField, appropriately + * shifted right, as a short.
+ * + *Many users of a BitField will want to treat the specified + * bits as an int value, and will not want to be aware that the + * value is stored as a BitField (and so shifted left so many + * bits).
+ * + * @see #setShortValue + * @param holder the short data containing the bits we're + * interested in + * @return the selected bits, shifted right appropriately + */ + public short getShortValue(final short holder) { + return (short) getValue(holder); + } + + /** + *Obtains the value for the specified BitField, unshifted.
+ * + * @param holder the int data containing the bits we're + * interested in + * @return the selected bits + */ + public int getRawValue(final int holder) { + return (holder & _mask); + } + + /** + *Obtains the value for the specified BitField, unshifted.
+ * + * @param holder the short data containing the bits we're + * interested in + * @return the selected bits + */ + public short getShortRawValue(final short holder) { + return (short) getRawValue(holder); + } + + /** + *Returns whether the field is set or not.
+ * + *This is most commonly used for a single-bit field, which is + * often used to represent a boolean value; the results of using + * it for a multi-bit field is to determine whether *any* of its + * bits are set.
+ * + * @param holder the int data containing the bits we're interested + * in + * @returntrue if any of the bits are set,
+     *  else false
+     */
+    public boolean isSet(final int holder) {
+        return (holder & _mask) != 0;
+    }
+
+    /**
+     * Returns whether all of the bits are set or not.
+ * + *This is a stricter test than {@link #isSet(int)},
+     * in that all of the bits in a multi-bit set must be set
+     * for this method to return true.
true if all of the bits are set,
+     *  else false
+     */
+    public boolean isAllSet(final int holder) {
+        return (holder & _mask) == _mask;
+    }
+
+    /**
+     * Replaces the bits with new values.
+ * + * @see #getValue + * @param holder the int data containint the bits we're + * interested in + * @param value the new value for the specified bits + * @return the value of holder with the bits from the value + * parameter replacing the old bits + */ + public int setValue(final int holder, final int value) { + return (holder & ~_mask) | ((value << _shift_count) & _mask); + } + + /** + *Replaces the bits with new values.
+ * + * @see #getShortValue + * @param holder the short data containing the bits we're + * interested in + * @param value the new value for the specified bits + * @return the value of holder with the bits from the value + * parameter replacing the old bits + */ + public short setShortValue(final short holder, final short value) { + return (short) setValue(holder, value); + } + + /** + *Clears the bits.
+ * + * @param holder the int data containing the bits we're + * interested in + * @return the value of holder with the specified bits cleared + * (set to0)
+     */
+    public int clear(final int holder) {
+        return holder & ~_mask;
+    }
+
+    /**
+     * Clears the bits.
+ * + * @param holder the short data containing the bits we're + * interested in + * @return the value of holder with the specified bits cleared + * (set to0)
+     */
+    public short clearShort(final short holder) {
+        return (short) clear(holder);
+    }
+
+    /**
+     * Clears the bits.
+ * + * @param holder the byte data containing the bits we're + * interested in + * + * @return the value of holder with the specified bits cleared + * (set to0)
+     */
+    public byte clearByte(final byte holder) {
+        return (byte) clear(holder);
+    }
+
+    /**
+     * Sets the bits.
+ * + * @param holder the int data containing the bits we're + * interested in + * @return the value of holder with the specified bits set + * to1
+     */
+    public int set(final int holder) {
+        return holder | _mask;
+    }
+
+    /**
+     * Sets the bits.
+ * + * @param holder the short data containing the bits we're + * interested in + * @return the value of holder with the specified bits set + * to1
+     */
+    public short setShort(final short holder) {
+        return (short) set(holder);
+    }
+
+    /**
+     * Sets the bits.
+ * + * @param holder the byte data containing the bits we're + * interested in + * + * @return the value of holder with the specified bits set + * to1
+     */
+    public byte setByte(final byte holder) {
+        return (byte) set(holder);
+    }
+
+    /**
+     * Sets a boolean BitField.
+ * + * @param holder the int data containing the bits we're + * interested in + * @param flag indicating whether to set or clear the bits + * @return the value of holder with the specified bits set or + * cleared + */ + public int setBoolean(final int holder, final boolean flag) { + return flag ? set(holder) : clear(holder); + } + + /** + *Sets a boolean BitField.
+ * + * @param holder the short data containing the bits we're + * interested in + * @param flag indicating whether to set or clear the bits + * @return the value of holder with the specified bits set or + * cleared + */ + public short setShortBoolean(final short holder, final boolean flag) { + return flag ? setShort(holder) : clearShort(holder); + } + + /** + *Sets a boolean BitField.
+ * + * @param holder the byte data containing the bits we're + * interested in + * @param flag indicating whether to set or clear the bits + * @return the value of holder with the specified bits set or + * cleared + */ + public byte setByteBoolean(final byte holder, final boolean flag) { + return flag ? setByte(holder) : clearByte(holder); + } + +} Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/BooleanUtils.java =================================================================== RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/BooleanUtils.java,v diff -u --- /dev/null 1 Jan 1970 00:00:00 -0000 +++ 3rdParty_sources/commons-lang/org/apache/commons/lang/BooleanUtils.java 30 Aug 2012 16:24:42 -0000 1.1 @@ -0,0 +1,676 @@ +/* ==================================================================== + * The Apache Software License, Version 1.1 + * + * Copyright (c) 2002-2003 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowledgement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowledgement may appear in the software itself, + * if and wherever such third-party acknowledgements normally appear. + * + * 4. The names "The Jakarta Project", "Commons", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Software Foundation. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + *Operations on boolean primitives and Boolean objects.
+ * + *This class tries to handle null input gracefully.
+ * An exception will not be thrown for a null input.
+ * Each method documents its behaviour in more detail.
BooleanUtils instances should NOT be constructed in standard programming.
+     * Instead, the class should be used as BooleanUtils.toBooleanObject(true);.
This constructor is public to permit tools that require a JavaBean instance + * to operate.
+ */ + public BooleanUtils() { + } + + // Boolean utilities + //-------------------------------------------------------------------------- + /** + *Negates the specified boolean.
+ * + *If null is passed in, null will be returned.
null if null input
+     */
+    public static Boolean negate(Boolean bool) {
+        if (bool == null) {
+            return null;
+        }
+        return (bool.booleanValue() ? Boolean.FALSE : Boolean.TRUE);
+    }
+    
+    // boolean Boolean methods
+    //-----------------------------------------------------------------------
+    /**
+     * Boolean factory that avoids creating new Boolean objecs all the time.
+ * + *This method was added to JDK1.4 but is available here for earlier JDKs.
+ * + * @param bool the boolean to convert + * @return Boolean.TRUE or Boolean.FALSE as appropriate + */ + public static Boolean toBooleanObject(boolean bool) { + return (bool ? Boolean.TRUE : Boolean.FALSE); + } + + /** + *Converts a Boolean to a boolean handling null
+     * by returning false.
true or false, 
+     *  null returns false
+     */
+    public static boolean toBoolean(Boolean bool) {
+        if (bool == null) {
+            return false;
+        }
+        return (bool.booleanValue() ? true : false);
+    }
+    
+    /**
+     * Converts a Boolean to a boolean handling null.
null
+     * @return true or false
+     */
+    public static boolean toBooleanDefaultIfNull(Boolean bool, boolean valueIfNull) {
+        if (bool == null) {
+            return valueIfNull;
+        }
+        return (bool.booleanValue() ? true : false);
+    }
+    
+    // Integer to Boolean methods
+    //-----------------------------------------------------------------------
+    /**
+     * Converts an int to a boolean using the convention that zero
+     * is false.
true if non-zero, false
+     *  if zero
+     */
+    public static boolean toBoolean(int value) {
+        return (value == 0 ? false : true);
+    }
+    
+    /**
+     * Converts an int to a Boolean using the convention that zero
+     * is false.
null if null
+     */
+    public static Boolean toBooleanObject(int value) {
+        return (value == 0 ? Boolean.FALSE : Boolean.TRUE);
+    }
+    
+    /**
+     * Converts an Integer to a Boolean using the convention that zero
+     * is false.
null will be converted to null.
null if null input
+     */
+    public static Boolean toBooleanObject(Integer value) {
+        if (value == null) {
+            return null;
+        }
+        return (value.intValue() == 0 ? Boolean.FALSE : Boolean.TRUE);
+    }
+    
+    /**
+     * Converts an int to a boolean specifying the conversion values.
+ * + * @param value the Integer to convert + * @param trueValue the value to match fortrue
+     * @param falseValue  the value to match for false
+     * @return true or false
+     * @throws IllegalArgumentException if no match
+     */
+    public static boolean toBoolean(int value, int trueValue, int falseValue) {
+        if (value == trueValue) {
+            return true;
+        } else if (value == falseValue) {
+            return false;
+        }
+        // no match
+        throw new IllegalArgumentException("The Integer did not match either specified value");
+    }
+    
+    /**
+     * Converts an Integer to a boolean specifying the conversion values.
+ * + * @param value the Integer to convert + * @param trueValue the value to match fortrue,
+     *  may be null
+     * @param falseValue  the value to match for false,
+     *  may be null
+     * @return true or false
+     * @throws IllegalArgumentException if no match
+     */
+    public static boolean toBoolean(Integer value, Integer trueValue, Integer falseValue) {
+        if (value == null) {
+            if (trueValue == null) {
+                return true;
+            } else if (falseValue == null) {
+                return false;
+            }
+        } else if (value.equals(trueValue)) {
+            return true;
+        } else if (value.equals(falseValue)) {
+            return false;
+        }
+        // no match
+        throw new IllegalArgumentException("The Integer did not match either specified value");
+    }
+    
+    /**
+     * Converts an int to a Boolean specifying the conversion values.
+ * + * @param value the Integer to convert + * @param trueValue the value to match fortrue
+     * @param falseValue  the value to match for false
+     * @param nullValue  the value to to match for null
+     * @return Boolean.TRUE, Boolean.FALSE, or null
+     * @throws IllegalArgumentException if no match
+     */
+    public static Boolean toBooleanObject(int value, int trueValue, int falseValue, int nullValue) {
+        if (value == trueValue) {
+            return Boolean.TRUE;
+        } else if (value == falseValue) {
+            return Boolean.FALSE;
+        } else if (value == nullValue) {
+            return null;
+        }
+        // no match
+        throw new IllegalArgumentException("The Integer did not match any specified value");
+    }
+    
+    /**
+     * Converts an Integer to a Boolean specifying the conversion values.
+ * + * @param value the Integer to convert + * @param trueValue the value to match fortrue,
+     *  may be null
+     * @param falseValue  the value to match for false,
+     *  may be null
+     * @param nullValue  the value to to match for null,
+     *  may be null
+     * @return Boolean.TRUE, Boolean.FALSE, or null
+     * @throws IllegalArgumentException if no match
+     */
+    public static Boolean toBooleanObject(Integer value, Integer trueValue, Integer falseValue, Integer nullValue) {
+        if (value == null) {
+            if (trueValue == null) {
+                return Boolean.TRUE;
+            } else if (falseValue == null) {
+                return Boolean.FALSE;
+            } else if (nullValue == null) {
+                return null;
+            }
+        } else if (value.equals(trueValue)) {
+            return Boolean.TRUE;
+        } else if (value.equals(falseValue)) {
+            return Boolean.FALSE;
+        } else if (value.equals(nullValue)) {
+            return null;
+        }
+        // no match
+        throw new IllegalArgumentException("The Integer did not match any specified value");
+    }
+    
+    // Boolean to Integer methods
+    //-----------------------------------------------------------------------
+    /**
+     * Converts a boolean to an int using the convention that
+     * zero is false.
true, zero if false
+     */
+    public static int toInteger(boolean bool) {
+        return (bool ? 1 : 0);
+    }
+    
+    /**
+     * Converts a boolean to an Integer using the convention that
+     * zero is false.
true, zero if false
+     */
+    public static Integer toIntegerObject(boolean bool) {
+        return (bool ? NumberUtils.INTEGER_ONE : NumberUtils.INTEGER_ZERO);
+    }
+    
+    /**
+     * Converts a Boolean to a Integer using the convention that
+     * zero is false.
null will be converted to null.
null if null
+     */
+    public static Integer toIntegerObject(Boolean bool) {
+        if (bool == null) {
+            return null;
+        }
+        return (bool.booleanValue() ? NumberUtils.INTEGER_ONE : NumberUtils.INTEGER_ZERO);
+    }
+    
+    /**
+     * Converts a boolean to an int specifying the conversion values.
+ * + * @param bool the to convert + * @param trueValue the value to return iftrue
+     * @param falseValue  the value to return if false
+     * @return the appropriate value
+     */
+    public static int toInteger(boolean bool, int trueValue, int falseValue) {
+        return (bool ? trueValue : falseValue);
+    }
+    
+    /**
+     * Converts a Boolean to an int specifying the conversion values.
+ * + * @param bool the Boolean to convert + * @param trueValue the value to return iftrue
+     * @param falseValue  the value to return if false
+     * @param nullValue  the value to return if null
+     * @return the appropriate value
+     */
+    public static int toInteger(Boolean bool, int trueValue, int falseValue, int nullValue) {
+        if (bool == null) {
+            return nullValue;
+        }
+        return (bool.booleanValue() ? trueValue : falseValue);
+    }
+    
+    /**
+     * Converts a boolean to an Integer specifying the conversion values.
+ * + * @param bool the to convert + * @param trueValue the value to return iftrue,
+     *  may be null
+     * @param falseValue  the value to return if false,
+     *  may be null
+     * @return the appropriate value
+     */
+    public static Integer toIntegerObject(boolean bool, Integer trueValue, Integer falseValue) {
+        return (bool ? trueValue : falseValue);
+    }
+    
+    /**
+     * Converts a Boolean to an Integer specifying the conversion values.
+ * + * @param bool the Boolean to convert + * @param trueValue the value to return iftrue,
+     *  may be null
+     * @param falseValue  the value to return if false,
+     *  may be null
+     * @param nullValue  the value to return if null,
+     *  may be null
+     * @return the appropriate value
+     */
+    public static Integer toIntegerObject(Boolean bool, Integer trueValue, Integer falseValue, Integer nullValue) {
+        if (bool == null) {
+            return nullValue;
+        }
+        return (bool.booleanValue() ? trueValue : falseValue);
+    }
+    
+    // String to Boolean methods
+    //-----------------------------------------------------------------------
+    /**
+     * Converts a String to a Boolean.
+ * + *'true', 'on' or 'yes'
+     * (case insensitive) will return true.
+     * 'false', 'off' or 'no'
+     * (case insensitive) will return false.
+     * Otherwise, null is returned.
null if no match or null input
+     */
+    public static Boolean toBooleanObject(String str) {
+        if ("true".equalsIgnoreCase(str)) {
+            return Boolean.TRUE;
+        } else if ("false".equalsIgnoreCase(str)) {
+            return Boolean.FALSE;
+        } else if ("on".equalsIgnoreCase(str)) {
+            return Boolean.TRUE;
+        } else if ("off".equalsIgnoreCase(str)) {
+            return Boolean.FALSE;
+        } else if ("yes".equalsIgnoreCase(str)) {
+            return Boolean.TRUE;
+        } else if ("no".equalsIgnoreCase(str)) {
+            return Boolean.FALSE;
+        }
+        // no match
+        return null;
+    }
+
+    /**
+     * Converts a String to a Boolean throwing an exception if no match.
+ * + * @param str the String to check + * @param trueString the String to match fortrue
+     *  (case sensitive), may be null
+     * @param falseString  the String to match for false
+     *  (case sensitive), may be null
+     * @param nullString  the String to match for null
+     *  (case sensitive), may be null
+     * @return the Boolean value of the string,
+     *  null if no match or null input
+     */
+    public static Boolean toBooleanObject(String str, String trueString, String falseString, String nullString) {
+        if (str == null) {
+            if (trueString == null) {
+                return Boolean.TRUE;
+            } else if (falseString == null) {
+                return Boolean.FALSE;
+            } else if (nullString == null) {
+                return null;
+            }
+        } else if (str.equals(trueString)) {
+            return Boolean.TRUE;
+        } else if (str.equals(falseString)) {
+            return Boolean.FALSE;
+        } else if (str.equals(nullString)) {
+            return null;
+        }
+        // no match
+        throw new IllegalArgumentException("The String did not match any specified value");
+    }
+
+    // String to boolean methods
+    //-----------------------------------------------------------------------
+    /**
+     * Converts a String to a boolean.
+ * + *'true', 'on' or 'yes'
+     * (case insensitive) will return true. Otherwise,
+     * false is returned.
false if no match
+     */
+    public static boolean toBoolean(String str) {
+        if ("true".equalsIgnoreCase(str)) {
+            return true;
+        } else if ("on".equalsIgnoreCase(str)) {
+            return true;
+        } else if ("yes".equalsIgnoreCase(str)) {
+            return true;
+        }
+        // no match
+        return false;
+    }
+
+    /**
+     * Converts a String to a Boolean throwing an exception if no match found.
+ * + *null is returned if there is no match.
+ * + * @param str the String to check + * @param trueString the String to match fortrue
+     *  (case sensitive), may be null
+     * @param falseString  the String to match for false
+     *  (case sensitive), may be null
+     * @return the boolean value of the string
+     * @throws IllegalArgumentException if the String doesn't match
+     */
+    public static boolean toBoolean(String str, String trueString, String falseString) {
+        if (str == null) {
+            if (trueString == null) {
+                return true;
+            } else if (falseString == null) {
+                return false;
+            }
+        } else if (str.equals(trueString)) {
+            return true;
+        } else if (str.equals(falseString)) {
+            return false;
+        }
+        // no match
+        throw new IllegalArgumentException("The String did not match either specified value");
+    }
+
+    // Boolean to String methods
+    //-----------------------------------------------------------------------
+    /**
+     * Converts a Boolean to a String returning 'true',
+     * 'false', or null.
'true', 'false',
+     *  or null
+     */
+    public static String toStringTrueFalse(Boolean bool) {
+        return toString(bool, "true", "false", null);
+    }
+    
+    /**
+     * Converts a Boolean to a String returning 'on',
+     * 'off', or null.
'on', 'off',
+     *  or null
+     */
+    public static String toStringOnOff(Boolean bool) {
+        return toString(bool, "on", "off", null);
+    }
+    
+    /**
+     * Converts a Boolean to a String returning 'yes',
+     * 'no', or null.
'yes', 'no',
+     *  or null
+     */
+    public static String toStringYesNo(Boolean bool) {
+        return toString(bool, "yes", "no", null);
+    }
+    
+    /**
+     * Converts a Boolean to a String returning one of the input Strings.
+ * + * @param bool the Boolean to check + * @param trueString the String to return iftrue,
+     *  may be null
+     * @param falseString  the String to return if false,
+     *  may be null
+     * @param nullString  the String to return if null,
+     *  may be null
+     * @return one of the three input Strings
+     */
+    public static String toString(Boolean bool, String trueString, String falseString, String nullString) {
+        if (bool == null) {
+            return nullString;
+        }
+        return (bool.booleanValue() ? trueString : falseString);
+    }
+    
+    // boolean to String methods
+    //-----------------------------------------------------------------------
+    /**
+     * Converts a boolean to a String returning 'true'
+     * or 'false'.
'true', 'false',
+     *  or null
+     */
+    public static String toStringTrueFalse(boolean bool) {
+        return toString(bool, "true", "false");
+    }
+    
+    /**
+     * Converts a boolean to a String returning 'on'
+     * or 'off'.
'on', 'off',
+     *  or null
+     */
+    public static String toStringOnOff(boolean bool) {
+        return toString(bool, "on", "off");
+    }
+    
+    /**
+     * Converts a boolean to a String returning 'yes'
+     * or 'no'.
'yes', 'no',
+     *  or null
+     */
+    public static String toStringYesNo(boolean bool) {
+        return toString(bool, "yes", "no");
+    }
+    
+    /**
+     * Converts a boolean to a String returning one of the input Strings.
+ * + * @param bool the Boolean to check + * @param trueString the String to return iftrue,
+     *  may be null
+     * @param falseString  the String to return if false,
+     *  may be null
+     * @return one of the two input Strings
+     */
+    public static String toString(boolean bool, String trueString, String falseString) {
+        return (bool ? trueString : falseString);
+    }
+    
+    // xor methods
+    // ----------------------------------------------------------------------
+    /**
+     * Performs an xor on a set of booleans.
+ * + * @param array an array ofbooleans
+     * @return true if the xor is successful.
+     * @throws IllegalArgumentException if array is null
+     * @throws IllegalArgumentException if array is empty.
+     */
+    public static boolean xor(boolean[] array) {
+        // Validates input
+        if (array == null) {
+            throw new IllegalArgumentException("The Array must not be null");
+        } else if (array.length == 0) {
+            throw new IllegalArgumentException("Array is empty");
+        }
+
+        // Loops through array, comparing each item
+        int trueCount = 0;
+        for (int i = 0; i < array.length; i++) {
+            // If item is true, and trueCount is < 1, increments count
+            // Else, xor fails
+            if (array[i]) {
+                if (trueCount < 1) {
+                    trueCount++;
+                } else {
+                    return false;
+                }
+            }
+        }
+
+        // Returns true if there was exactly 1 true item
+        return trueCount == 1;
+    }
+
+    /**
+     * Performs an xor on an array of Booleans.
+     * 
+     * @param array  an array of Booleans
+     * @return true if the xor is successful.
+     * @throws IllegalArgumentException if array is null
+     * @throws IllegalArgumentException if array is empty.
+     * @throws IllegalArgumentException if array contains a null
+     */
+    public static Boolean xor(Boolean[] array) {
+        if (array == null) {
+            throw new IllegalArgumentException("The Array must not be null");
+        } else if (array.length == 0) {
+            throw new IllegalArgumentException("Array is empty");
+        }
+        boolean[] primitive = null;
+        try {
+            primitive = ArrayUtils.toPrimitive(array);
+        } catch (NullPointerException ex) {
+            throw new IllegalArgumentException("The array must not conatin any null elements");
+        }
+        return (xor(primitive) ? Boolean.TRUE : Boolean.FALSE);
+    }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/CharRange.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/CharRange.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/CharRange.java	30 Aug 2012 16:24:42 -0000	1.1
@@ -0,0 +1,266 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang;
+
+import java.io.Serializable;
+
+/**
+ * A contiguous range of characters, optionally negated.
+ * 
+ * Instances are immutable.
+ *
+ * @author Henri Yandell
+ * @author Stephen Colebourne
+ * @author Chris Feldhacker
+ * @author Gary Gregory
+ * @since 1.0
+ * @version $Id: CharRange.java,v 1.1 2012/08/30 16:24:42 marcin Exp $
+ */
+public final class CharRange implements Serializable {
+
+    /** Serialization lock, Lang version 2.0. */
+    private static final long serialVersionUID = 8270183163158333422L;
+    
+    /** The first character, inclusive, in the range. */
+    private final char start;
+    /** The last character, inclusive, in the range. */
+    private final char end;
+    /** True if the range is everything except the characters specified. */
+    private final boolean negated;
+    
+    /** Cached toString. */
+    private transient String iToString;
+
+    //-----------------------------------------------------------------------
+    /**
+     * Constructs a CharRange over a single character.
+     *
+     * @param ch  only character in this range
+     */
+    public CharRange(char ch) {
+        this(ch, ch, false);
+    }
+
+    /**
+     * Constructs a CharRange over a single character,
+     * optionally negating the range.
+     *
+     * A negated range includes everything except the specified char.
+     *
+     * @param ch  only character in this range
+     * @param negated  true to express everything except the range
+     */
+    public CharRange(char ch, boolean negated) {
+        this(ch, ch, negated);
+    }
+
+    /**
+     * Constructs a CharRange over a set of characters.
+     *
+     * @param start  first character, inclusive, in this range
+     * @param end  last character, inclusive, in this range
+     */
+    public CharRange(char start, char end) {
+        this(start, end, false);
+    }
+
+    /**
+     * Constructs a CharRange over a set of characters,
+     * optionally negating the range.
+     *
+     * A negated range includes everything except that defined by the
+     * start and end characters.
+     * 
+     * If start and end are in the wrong order, they are reversed.
+     * Thus a-e is the same as e-a.
+     *
+     * @param start  first character, inclusive, in this range
+     * @param end  last character, inclusive, in this range
+     * @param negated  true to express everything except the range
+     */
+    public CharRange(char start, char end, boolean negated) {
+        super();
+        if (start > end) {
+            char temp = start;
+            start = end;
+            end = temp;
+        }
+        
+        this.start = start;
+        this.end = end;
+        this.negated = negated;
+    }
+
+    // Accessors
+    //-----------------------------------------------------------------------
+    /**
+     * Gets the start character for this character range.
+     * 
+     * @return the start char (inclusive)
+     */
+    public char getStart() {
+        return this.start;
+    }
+
+    /**
+     * Gets the end character for this character range.
+     * 
+     * @return the end char (inclusive)
+     */
+    public char getEnd() {
+        return this.end;
+    }
+
+    /**
+     * Is this CharRange negated.
+     * 
+     * A negated range includes everything except that defined by the
+     * start and end characters.
+     *
+     * @return true is negated
+     */
+    public boolean isNegated() {
+        return negated;
+    }
+
+    // Contains
+    //-----------------------------------------------------------------------
+    /**
+     * Is the character specified contained in this range.
+     *
+     * @param ch  the character to check
+     * @return true if this range contains the input character
+     */
+    public boolean contains(char ch) {
+        return ((ch >= start && ch <= end) != negated);
+    }
+
+    /**
+     * Are all the characters of the passed in range contained in
+     * this range.
+     *
+     * @param range  the range to check against
+     * @return true if this range entirely contains the input range
+     * @throws IllegalArgumentException if null input
+     */
+    public boolean contains(CharRange range) {
+        if (range == null) {
+            throw new IllegalArgumentException("The Range must not be null");
+        }
+        if (negated) {
+            if (range.negated) {
+                return (start >= range.start && end <= range.end);
+            } else {
+                return (range.end < start || range.start > end);
+            }
+        } else {
+            if (range.negated) {
+                return (start == 0 && end == Character.MAX_VALUE);
+            } else {
+                return (start <= range.start && end >= range.end);
+            }
+        }
+    }
+
+    // Basics
+    //-----------------------------------------------------------------------
+    /**
+     * Compares two CharRange objects, returning true if they represent
+     * exactly the same range of characters defined in the same way.
+     * 
+     * @param obj  the object to compare to
+     * @return true if equal
+     */
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+        if (obj instanceof CharRange == false) {
+            return false;
+        }
+        CharRange other = (CharRange) obj;
+        return (start == other.start && end == other.end && negated == other.negated);
+    }
+
+    /**
+     * Gets a hashCode compatable with the equals method.
+     * 
+     * @return a suitable hashCode
+     */
+    public int hashCode() {
+        return 83 + start + 7 * end + (negated ? 1 : 0);
+    }
+    
+    /**
+     * Gets a string representation of the character range.
+     * 
+     * @return string representation of this range
+     */
+    public String toString() {
+        if (iToString == null) {
+            StringBuffer buf = new StringBuffer(4);
+            if (isNegated()) {
+                buf.append('^');
+            }
+            buf.append(start);
+            if (start != end) {
+                buf.append('-');
+                buf.append(end);
+            }
+            iToString = buf.toString();
+        }
+        return iToString;
+    }
+    
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/CharSet.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/CharSet.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/CharSet.java	30 Aug 2012 16:24:42 -0000	1.1
@@ -0,0 +1,317 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang;
+
+import java.io.Serializable;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.Map;
+import java.util.Set;
+
+/**
+ * A set of characters.
+ *
+ * Instances are immutable, but instances of subclasses may not be.
+ *
+ * @author Henri Yandell
+ * @author Stephen Colebourne
+ * @author Phil Steitz
+ * @author Pete Gieser
+ * @author Gary Gregory
+ * @since 1.0
+ * @version $Id: CharSet.java,v 1.1 2012/08/30 16:24:42 marcin Exp $
+ */
+public class CharSet implements Serializable {
+
+    /** Serialization lock, Lang version 2.0. */
+    private static final long serialVersionUID = 5947847346149275958L;
+
+    /** 
+     * A CharSet defining no characters. 
+     * @since 2.0
+     */
+    public static final CharSet EMPTY = new CharSet((String) null);
+
+    /** 
+     * A CharSet defining ASCII alphabetic characters "a-zA-Z".
+     * @since 2.0
+     */
+    public static final CharSet ASCII_ALPHA = new CharSet("a-zA-Z");
+
+    /** 
+     * A CharSet defining ASCII alphabetic characters "a-z".
+     * @since 2.0
+     */
+    public static final CharSet ASCII_ALPHA_LOWER = new CharSet("a-z");
+
+    /** 
+     * A CharSet defining ASCII alphabetic characters "A-Z".
+     * @since 2.0
+     */
+    public static final CharSet ASCII_ALPHA_UPPER = new CharSet("A-Z");
+
+    /** 
+     * A CharSet defining ASCII alphabetic characters "0-9".
+     * @since 2.0
+     */
+    public static final CharSet ASCII_NUMERIC = new CharSet("0-9");
+
+    /**
+     * A Map of the common cases used in the factory.
+     * Subclasses can add more common patterns if desired.
+     * @since 2.0
+     */
+    protected static final Map COMMON = new HashMap();
+    
+    static {
+        COMMON.put(null, EMPTY);
+        COMMON.put("", EMPTY);
+        COMMON.put("a-zA-Z", ASCII_ALPHA);
+        COMMON.put("A-Za-z", ASCII_ALPHA);
+        COMMON.put("a-z", ASCII_ALPHA_LOWER);
+        COMMON.put("A-Z", ASCII_ALPHA_UPPER);
+        COMMON.put("0-9", ASCII_NUMERIC);
+    }
+
+    /** The set of CharRange objects. */
+    private Set set = new HashSet();
+
+    //-----------------------------------------------------------------------
+    /**
+     * Factory method to create a new CharSet using a special syntax.
+     *
+     * 
+     *  null or empty string ("")
+     * - set containing no characters 
+     *  - Single character, such as "a"
+     *  - set containing just that character
 
+     *  - Multi character, such as "a-e"
+     *  - set containing characters from one character to the other
 
+     *  - Negated, such as "^a" or "^a-e"
+     *  - set containing all characters except those defined
 
+     *  - Combinations, such as "abe-g"
+     *  - set containing all the characters from the individual sets
 
+     * 
+     *
+     * The matching order is:
+     * 
+     *  - Negated multi character range, such as "^a-e"
+     *  
 - Ordinary multi character range, such as "a-e"
+     *  
 - Negated single character, such as "^a"
+     *  
 - Ordinary single character, such as "a"
+     * 
 
+     * Matching works left to right. Once a match is found the
+     * search starts again from the next character.
+     *
+     * If the same range is defined twice using the same syntax, only
+     * one range will be kept.
+     * Thus, "a-ca-c" creates only one range of "a-c".
+     *
+     * If the start and end of a range are in the wrong order,
+     * they are reversed. Thus "a-e" is the same as "e-a".
+     * As a result, "a-ee-a" would create only one range,
+     * as the "a-e" and "e-a" are the same.
+     *
+     * The set of characters represented is the union of the specified ranges.
+     *
+     * All CharSet objects returned by this method will be immutable.
+     *
+     * @param setStr  the String describing the set, may be null
+     * @return a CharSet instance
+     * @since 2.0
+     */
+    public static CharSet getInstance(String setStr) {
+        Object set = COMMON.get(setStr);
+        if (set != null) {
+            return (CharSet) set;
+        }
+        return new CharSet(setStr);
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Constructs a new CharSet using the set syntax.
+     *
+     * @param setStr  the String describing the set, may be null
+     * @since 2.0
+     */
+    protected CharSet(String setStr) {
+        super();
+        add(setStr);
+    }
+
+    /**
+     * Constructs a new CharSet using the set syntax.
+     * Each string is merged in with the set.
+     *
+     * @param set  Strings to merge into the initial set
+     * @throws NullPointerException if set is null
+     */
+    protected CharSet(String[] set) {
+        super();
+        int sz = set.length;
+        for (int i = 0; i < sz; i++) {
+            add(set[i]);
+        }
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Add a set definition string to the CharSet.
+     *
+     * @param str  set definition string
+     */
+    protected void add(String str) {
+        if (str == null) {
+            return;
+        }
+
+        int len = str.length();
+        int pos = 0;
+        while (pos < len) {
+            int remainder = (len - pos);
+            if (remainder >= 4 && str.charAt(pos) == '^' && str.charAt(pos + 2) == '-') {
+                // negated range
+                set.add(new CharRange(str.charAt(pos + 1), str.charAt(pos + 3), true));
+                pos += 4;
+            } else if (remainder >= 3 && str.charAt(pos + 1) == '-') {
+                // range
+                set.add(new CharRange(str.charAt(pos), str.charAt(pos + 2)));
+                pos += 3;
+            } else if (remainder >= 2 && str.charAt(pos) == '^') {
+                // negated char
+                set.add(new CharRange(str.charAt(pos + 1), true));
+                pos += 2;
+            } else {
+                // char
+                set.add(new CharRange(str.charAt(pos)));
+                pos += 1;
+            }
+        }
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Gets the internal set as an array of CharRange objects.
+     *
+     * @return an array of immutable CharRange objects
+     * @since 2.0
+     */
+    public CharRange[] getCharRanges() {
+        return (CharRange[]) set.toArray(new CharRange[set.size()]);
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Does the CharSet contain the specified
+     * character ch.
+     *
+     * @param ch  the character to check for
+     * @return true if the set contains the characters
+     */
+    public boolean contains(char ch) {
+        for (Iterator it = set.iterator(); it.hasNext();) {
+            CharRange range = (CharRange) it.next();
+            if (range.contains(ch)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    // Basics
+    //-----------------------------------------------------------------------
+    /**
+     * Compares two CharSet objects, returning true if they represent
+     * exactly the same set of characters defined in the same way.
+     *
+     * The two sets abc and a-c are not
+     * equal according to this method.
+     *
+     * @param obj  the object to compare to
+     * @return true if equal
+     * @since 2.0
+     */
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+        if (obj instanceof CharSet == false) {
+            return false;
+        }
+        CharSet other = (CharSet) obj;
+        return (set.equals(other.set));
+    }
+
+    /**
+     * Gets a hashCode compatable with the equals method.
+     *
+     * @return a suitable hashCode
+     * @since 2.0
+     */
+    public int hashCode() {
+        return 89 + set.hashCode();
+    }
+
+    /**
+     * Gets a string representation of the set.
+     *
+     * @return string representation of the set
+     */
+    public String toString() {
+        return set.toString();
+    }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/CharSetUtils.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/CharSetUtils.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/CharSetUtils.java	30 Aug 2012 16:24:42 -0000	1.1
@@ -0,0 +1,417 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang;
+
+/**
+ * Operations on CharSets.
+ *
+ * This class handles null input gracefully.
+ * An exception will not be thrown for a null input.
+ * Each method documents its behaviour in more detail.
+ * 
+ * @see CharSet
+ * @author Henri Yandell
+ * @author Stephen Colebourne
+ * @author Phil Steitz
+ * @author Gary Gregory
+ * @since 1.0
+ * @version $Id: CharSetUtils.java,v 1.1 2012/08/30 16:24:42 marcin Exp $
+ */
+public class CharSetUtils {
+
+    /**
+     * CharSetUtils instances should NOT be constructed in standard programming.
+     * Instead, the class should be used as CharSetUtils.evaluateSet(null);.
+     *
+     * This constructor is public to permit tools that require a JavaBean instance
+     * to operate.
+     */
+    public CharSetUtils() {
+    }
+
+    // Factory
+    //-----------------------------------------------------------------------
+    /**
+     * Creates a CharSet instance which allows a certain amount of
+     * set logic to be performed.
+     * The syntax is:
+     * 
+     *  - "aeio" which implies 'a','e',..
 
+     *  - "^e" implies not e.
 
+     *  - "ej-m" implies e,j->m. e,j,k,l,m.
 
+     * 
+     * 
+     * 
+     * CharSetUtils.evaluateSet(null)    = null
+     * CharSetUtils.evaluateSet([])      = CharSet matching nothing
+     * CharSetUtils.evaluateSet(["a-e"]) = CharSet matching a,b,c,d,e
+     * 
+     *
+     * @param set  the set, may be null
+     * @return a CharSet instance, null if null input
+     * @deprecated Use {@link CharSet#getInstance(String)}.
+     *             Method will be removed in Commons Lang 3.0.
+     */
+    public static CharSet evaluateSet(String[] set) {
+        if (set == null) {
+            return null;
+        }
+        return new CharSet(set); 
+    }
+
+    // Squeeze
+    //-----------------------------------------------------------------------
+    /**
+     * Squeezes any repititions of a character that is mentioned in the
+     * supplied set.
+     *
+     * 
+     * CharSetUtils.squeeze(null, *)        = null
+     * CharSetUtils.squeeze("", *)          = ""
+     * CharSetUtils.squeeze(*, null)        = *
+     * CharSetUtils.squeeze(*, "")          = *
+     * CharSetUtils.squeeze("hello", "k-p") = "helo"
+     * CharSetUtils.squeeze("hello", "a-e") = "hello"
+     * 
+     *
+     * @see #evaluateSet(java.lang.String[]) for set-syntax.
+     * @param str  the string to squeeze, may be null
+     * @param set  the character set to use for manipulation, may be null
+     * @return modified String, null if null string input
+     */
+    public static String squeeze(String str, String set) {
+        if (str == null || str.length() == 0 || set == null || set.length() == 0) {
+            return str;
+        }
+        String[] strs = new String[1];
+        strs[0] = set;
+        return squeeze(str, strs);
+    }
+
+    /**
+     * Squeezes any repititions of a character that is mentioned in the
+     * supplied set.
+     *
+     * An example is:
+     * 
+     *   - squeeze("hello", {"el"}) => "helo"
 
+     * 
+     * 
+     * @see #evaluateSet(java.lang.String[]) for set-syntax.
+     * @param str  the string to squeeze, may be null
+     * @param set  the character set to use for manipulation, may be null
+     * @return modified String, null if null string input
+     */
+    public static String squeeze(String str, String[] set) {
+        if (str == null || str.length() == 0 || set == null || set.length == 0) {
+            return str;
+        }
+        CharSet chars = evaluateSet(set);
+        StringBuffer buffer = new StringBuffer(str.length());
+        char[] chrs = str.toCharArray();
+        int sz = chrs.length;
+        char lastChar = ' ';
+        char ch = ' ';
+        for (int i = 0; i < sz; i++) {
+            ch = chrs[i];
+            if (chars.contains(ch)) {
+                if ((ch == lastChar) && (i != 0)) {
+                    continue;
+                }
+            }
+            buffer.append(ch);
+            lastChar = ch;
+        }
+        return buffer.toString();
+    }
+
+    // Count
+    //-----------------------------------------------------------------------
+    /**
+     * Takes an argument in set-syntax, see evaluateSet,
+     * and returns the number of characters present in the specified string.
+     *
+     * 
+     * CharSetUtils.count(null, *)        = 0
+     * CharSetUtils.count("", *)          = 0
+     * CharSetUtils.count(*, null)        = 0
+     * CharSetUtils.count(*, "")          = 0
+     * CharSetUtils.count("hello", "k-p") = 3
+     * CharSetUtils.count("hello", "a-e") = 1
+     * 
+     *
+     * @see #evaluateSet(java.lang.String[]) for set-syntax.
+     * @param str  String to count characters in, may be null
+     * @param set  String set of characters to count, may be null
+     * @return character count, zero if null string input
+     */
+    public static int count(String str, String set) {
+        if (str == null || str.length() == 0 || set == null || set.length() == 0) {
+            return 0;
+        }
+        String[] strs = new String[1];
+        strs[0] = set;
+        return count(str, strs);
+    }
+    
+    /**
+     * Takes an argument in set-syntax, see evaluateSet,
+     * and returns the number of characters present in the specified string.
+     *
+     * An example would be:
+     * 
+     *  - count("hello", {"c-f", "o"}) returns 2.
 
+     * 
+     *
+     * @see #evaluateSet(java.lang.String[]) for set-syntax.
+     * @param str  String to count characters in, may be null
+     * @param set  String[] set of characters to count, may be null
+     * @return character count, zero if null string input
+     */
+    public static int count(String str, String[] set) {
+        if (str == null || str.length() == 0 || set == null || set.length == 0) {
+            return 0;
+        }
+        CharSet chars = evaluateSet(set);
+        int count = 0;
+        char[] chrs = str.toCharArray();
+        int sz = chrs.length;
+        for(int i=0; iTakes an argument in set-syntax, see evaluateSet,
+     * and keeps any of characters present in the specified string.
+     *
+     * 
+     * CharSetUtils.keep(null, *)        = null
+     * CharSetUtils.keep("", *)          = ""
+     * CharSetUtils.keep(*, null)        = ""
+     * CharSetUtils.keep(*, "")          = ""
+     * CharSetUtils.keep("hello", "hl") = "hll"
+     * CharSetUtils.keep("hello", "le") = "ell"
+     * 
+     *
+     * @see #evaluateSet(java.lang.String[]) for set-syntax.
+     * @param str  String to keep characters from, may be null
+     * @param set  String set of characters to keep, may be null
+     * @return modified String, null if null string input
+     * @since 2.0
+     */
+    public static String keep(String str, String set) {
+        if (str == null) {
+            return null;
+        }
+        if (str.length() == 0 || set == null || set.length() == 0) {
+            return "";
+        }
+        String[] strs = new String[1];
+        strs[0] = set;
+        return keep(str, strs);
+    }
+    
+    /**
+     * Takes an argument in set-syntax, see evaluateSet,
+     * and keeps any of characters present in the specified string.
+     *
+     * An example would be:
+     * 
+     *  - keep("hello", {"c-f", "o"})
+     *   returns "hll"
 
+     * 
+     *
+     * @see #evaluateSet(java.lang.String[]) for set-syntax.
+     * @param str  String to keep characters from, may be null
+     * @param set  String[] set of characters to keep, may be null
+     * @return modified String, null if null string input
+     * @since 2.0
+     */
+    public static String keep(String str, String[] set) {
+        if (str == null) {
+            return null;
+        }
+        if (str.length() == 0 || set == null || set.length == 0) {
+            return "";
+        }
+        return modify(str, set, true);
+    }
+
+    // Delete
+    //-----------------------------------------------------------------------
+    /**
+     * Takes an argument in set-syntax, see evaluateSet,
+     * and deletes any of characters present in the specified string.
+     *
+     * 
+     * CharSetUtils.delete(null, *)        = null
+     * CharSetUtils.delete("", *)          = ""
+     * CharSetUtils.delete(*, null)        = *
+     * CharSetUtils.delete(*, "")          = *
+     * CharSetUtils.delete("hello", "hl") = "hll"
+     * CharSetUtils.delete("hello", "le") = "ell"
+     * 
+     *
+     * @see #evaluateSet(java.lang.String[]) for set-syntax.
+     * @param str  String to delete characters from, may be null
+     * @param set  String set of characters to delete, may be null
+     * @return modified String, null if null string input
+     */
+    public static String delete(String str, String set) {
+        if (str == null || str.length() == 0 || set == null || set.length() == 0) {
+            return str;
+        }
+        String[] strs = new String[1];
+        strs[0] = set;
+        return delete(str, strs);
+    }
+    
+    /**
+     * Takes an argument in set-syntax, see evaluateSet,
+     * and deletes any of characters present in the specified string.
+     *
+     * An example would be:
+     * 
+     *  - delete("hello", {"c-f", "o"}) returns
+     *   "hll"
 
+     * 
+     *
+     * @see #evaluateSet(java.lang.String[]) for set-syntax.
+     * @param str  String to delete characters from, may be null
+     * @param set  String[] set of characters to delete, may be null
+     * @return modified String, null if null string input
+     */
+    public static String delete(String str, String[] set) {
+        if (str == null || str.length() == 0 || set == null || set.length == 0) {
+            return str;
+        }
+        return modify(str, set, false);
+    }
+
+    //-----------------------------------------------------------------------
+    // Implementation of delete and keep
+    private static String modify(String str, String[] set, boolean expect) {
+        CharSet chars = evaluateSet(set);
+        StringBuffer buffer = new StringBuffer(str.length());
+        char[] chrs = str.toCharArray();
+        int sz = chrs.length;
+        for(int i=0; iTranslate characters in a String.
+     * This is a multi character search and replace routine.
+     *
+     * An example is:
+     * 
+     *   - translate("hello", "ho", "jy")
+     *    => jelly
 
+     * 
+     *
+     * If the length of characters to search for is greater than the
+     * length of characters to replace, then the last character is 
+     * used.
+     * 
+     * 
+     * CharSetUtils.translate(null, *, *) = null
+     * CharSetUtils.translate("", *, *) = ""
+     * 
+     *
+     * @param str  String to replace characters in, may be null
+     * @param searchChars   a set of characters to search for, must not be null
+     * @param replaceChars  a set of characters to replace, must not be null or empty ("")
+     * @return translated String, null if null string input
+     * @throws NullPointerException if with or repl 
+     *  is null
+     * @throws ArrayIndexOutOfBoundsException if with is empty ("")
+     * @deprecated Use {@link StringUtils#replaceChars(String, String, String)}.
+     *             Method will be removed in Commons Lang 3.0.
+     */
+    public static String translate(String str, String searchChars, String replaceChars) {
+        if (str == null || str.length() == 0) {
+            return str;
+        }
+        StringBuffer buffer = new StringBuffer(str.length());
+        char[] chrs = str.toCharArray();
+        char[] withChrs = replaceChars.toCharArray();
+        int sz = chrs.length;
+        int withMax = replaceChars.length() - 1;
+        for(int i=0; i withMax) {
+                    idx = withMax;
+                }
+                buffer.append(withChrs[idx]);
+            } else {
+                buffer.append(chrs[i]);
+            }
+        }
+        return buffer.toString();
+    }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/ClassUtils.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/ClassUtils.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/ClassUtils.java	30 Aug 2012 16:24:42 -0000	1.1
@@ -0,0 +1,533 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+/**
+ * Operates on classes without using reflection.
+ *
+ * This class handles invalid null inputs as best it can.
+ * Each method documents its behaviour in more detail.
+ *
+ * @author Stephen Colebourne
+ * @author Gary Gregory
+ * @since 2.0
+ * @version $Id: ClassUtils.java,v 1.1 2012/08/30 16:24:42 marcin Exp $
+ */
+public class ClassUtils {
+
+    /**
+     * The package separator character: ..
+     */
+    public static final char PACKAGE_SEPARATOR_CHAR = '.';
+    
+    /**
+     * The package separator String: ..
+     */
+    public static final String PACKAGE_SEPARATOR = String.valueOf(PACKAGE_SEPARATOR_CHAR);
+    
+    /**
+     * The inner class separator character: $.
+     */
+    public static final char INNER_CLASS_SEPARATOR_CHAR = '$';
+    
+    /**
+     * The inner class separator String: $.
+     */
+    public static final String INNER_CLASS_SEPARATOR = String.valueOf(INNER_CLASS_SEPARATOR_CHAR);
+    
+    /**
+     * ClassUtils instances should NOT be constructed in standard programming.
+     * Instead, the class should be used as
+     * ClassUtils.getShortClassName(cls).
+     *
+     * This constructor is public to permit tools that require a JavaBean
+     * instance to operate.
+     */
+    public ClassUtils() {
+    }
+
+    // Short class name
+    // ----------------------------------------------------------------------
+    /**
+     * Gets the class name minus the package name for an Object.
+     * 
+     * @param object  the class to get the short name for, may be null
+     * @param valueIfNull  the value to return if null
+     * @return the class name of the object without the package name, or the null value
+     */
+    public static String getShortClassName(Object object, String valueIfNull) {
+        if (object == null) {
+            return valueIfNull;
+        }
+        return getShortClassName(object.getClass().getName());
+    }
+    
+    /**
+     * Gets the class name minus the package name from a Class.
+     * 
+     * @param cls  the class to get the short name for, must not be
+     *  null
+     * @return the class name without the package name
+     * @throws IllegalArgumentException if the class is null
+     */
+    public static String getShortClassName(Class cls) {
+        if (cls == null) {
+            throw new IllegalArgumentException("The class must not be null");
+        }
+        return getShortClassName(cls.getName());
+    }
+    
+    /**
+     * Gets the class name minus the package name from a String.
+     *
+     * The string passed in is assumed to be a class name - it is not checked.
+     * 
+     * @param className  the className to get the short name for,
+     *  must not be empty or null
+     * @return the class name of the class without the package name
+     * @throws IllegalArgumentException if the className is empty
+     */
+    public static String getShortClassName(String className) {
+        if (StringUtils.isEmpty(className)) {
+            throw new IllegalArgumentException("The class name must not be empty");
+        }
+        char[] chars = className.toCharArray();
+        int lastDot = 0;
+        for (int i = 0; i < chars.length; i++) {
+            if (chars[i] == PACKAGE_SEPARATOR_CHAR) {
+                lastDot = i + 1;
+            } else if (chars[i] == INNER_CLASS_SEPARATOR_CHAR) {  // handle inner classes
+                chars[i] = PACKAGE_SEPARATOR_CHAR;
+            }
+        }
+        return new String(chars, lastDot, chars.length - lastDot);
+    }
+    
+    // Package name
+    // ----------------------------------------------------------------------
+    /**
+     * Gets the package name of an Object.
+     * 
+     * @param object  the class to get the package name for, may be null
+     * @param valueIfNull  the value to return if null
+     * @return the package name of the object, or the null value
+     */
+    public static String getPackageName(Object object, String valueIfNull) {
+        if (object == null) {
+            return valueIfNull;
+        }
+        return getPackageName(object.getClass().getName());
+    }
+    
+    /**
+     * Gets the package name of a Class.
+     * 
+     * @param cls  the class to get the package name for,
+     *  must not be null
+     * @return the package name
+     * @throws IllegalArgumentException if the class is null
+     */
+    public static String getPackageName(Class cls) {
+        if (cls == null) {
+            throw new IllegalArgumentException("The class must not be null");
+        }
+        return getPackageName(cls.getName());
+    }
+    
+    /**
+     * Gets the package name from a String.
+     *
+     * The string passed in is assumed to be a class name - it is not checked.
+     * 
+     * @param className  the className to get the package name for,
+     *  must not be empty or null
+     * @return the package name
+     * @throws IllegalArgumentException if the className is empty
+     */
+    public static String getPackageName(String className) {
+        if (StringUtils.isEmpty(className)) {
+            throw new IllegalArgumentException("The class name must not be empty");
+        }
+        int i = className.lastIndexOf(PACKAGE_SEPARATOR_CHAR);
+        if (i == -1) {
+            return "";
+        }
+        return className.substring(0, i);
+    }
+    
+    // Superclasses/Superinterfaces
+    // ----------------------------------------------------------------------
+    /**
+     * Gets a List of superclasses for the given class.
+     * 
+     * @param cls  the class to look up, must not be null
+     * @return the List of superclasses in order going up from this one
+     *  null if null input
+     */
+    public static List getAllSuperclasses(Class cls) {
+        if (cls == null) {
+            return null;
+        }
+        List classes = new ArrayList();
+        Class superclass = cls.getSuperclass();
+        while (superclass != null) {
+            classes.add(superclass);
+            superclass = superclass.getSuperclass();
+        }
+        return classes;
+    }
+    
+    /**
+     * Gets a List of all interfaces implemented by the given
+     * class and its superclasses.
+     *
+     * The order is determined by looking through each interface in turn as
+     * declared in the source file and following its hieracrchy up. Then each 
+     * superclass is considered in the same way. Later duplicates are ignored, 
+     * so the order is maintained.
+     * 
+     * @param cls  the class to look up, must not be null
+     * @return the List of interfaces in order,
+     *  null if null input
+     */
+    public static List getAllInterfaces(Class cls) {
+        if (cls == null) {
+            return null;
+        }
+        List list = new ArrayList();
+        while (cls != null) {
+            Class[] interfaces = cls.getInterfaces();
+            for (int i = 0; i < interfaces.length; i++) {
+                if (list.contains(interfaces[i]) == false) {
+                    list.add(interfaces[i]);
+                }
+                List superInterfaces = getAllInterfaces(interfaces[i]);
+                for (Iterator it = superInterfaces.iterator(); it.hasNext();) {
+                    Class intface = (Class) it.next();
+                    if (list.contains(intface) == false) {
+                        list.add(intface);
+                    }
+                }
+            }
+            cls = cls.getSuperclass();
+        }
+        return list;
+    }
+    
+//    /**
+//     * Gets a List of subclasses of the specified class.
+//     *
+//     * This method searches the classpath to find all the subclasses
+//     * of a particular class available. No classes are loaded, the 
+//     * returned list contains class names, not classes.
+//     *
+//     * @param cls  the class to find subclasses for
+//     * @return the List of subclass String class names
+//     * @throws IllegalArgumentException if the class is null
+//     */
+//    public static List getAllSubclassNames(Class cls) {
+//        if (cls == null) {
+//            throw new IllegalArgumentException("The class must not be null");
+//        }
+//        // TODO Use JavaWorld tip for searching the classpath
+//        return null;
+//    }
+
+//    /**
+//     * Gets a List of subclasses of the specified class.
+//     *
+//     * This method searches the classpath to find all the subclasses
+//     * of a particular class available.
+//     *
+//     * @param cls  the class to find subclasses for
+//     * @return the List of subclasses
+//     * @throws IllegalArgumentException if the class is null
+//     */
+//    public static List getAllSubclasses(Class cls) {
+//        List names = getAllSubclassNames(cls);
+//        return convertClassNamesToClasses(names);
+//    }
+
+//    /**
+//     * Gets a List of implementations of the specified interface.
+//     *
+//     * This method searches the classpath to find all the implementations
+//     * of a particular interface available. No classes are loaded, the 
+//     * returned list contains class names, not classes.
+//     *
+//     * @param cls  the class to find sub classes for
+//     * @return the List of implementation String class names
+//     * @throws IllegalArgumentException if the class is null
+//     */
+//    public static List getAllImplementationClassNames(Class cls) {
+//        if (cls == null) {
+//            throw new IllegalArgumentException("The class must not be null");
+//        }
+//        // TODO Use JavaWorld tip for searching the classpath
+//        return null;
+//    }
+
+    // Convert list
+    // ----------------------------------------------------------------------
+    /**
+     * Given a List of class names, this method converts them into classes.
+     *
+     * A new List is returned. If the class name cannot be found, null
+     * is stored in the List. If the class name in the List is
+     * null, null is stored in the output List.
+     * 
+     * @param classNames  the classNames to change
+     * @return a List of Class objects corresponding to the class names,
+     *  null if null input
+     * @throws ClassCastException if classNames contains a non String entry
+     */
+    public static List convertClassNamesToClasses(List classNames) {
+        if (classNames == null) {
+            return null;
+        }
+        List classes = new ArrayList(classNames.size());
+        for (Iterator it = classNames.iterator(); it.hasNext();) {
+            String className = (String) it.next();
+            try {
+                classes.add(Class.forName(className));
+            } catch (Exception ex) {
+                classes.add(null);
+            }
+        }
+        return classes;
+    }
+    
+    /**
+     * Given a List of Class objects, this method converts
+     * them into class names.
+     *
+     * A new List is returned. null objects will be copied into
+     * the returned list as null.
+     * 
+     * @param classes  the classes to change
+     * @return a List of Class objects corresponding to the class names,
+     *  null if null input
+     * @throws ClassCastException if classNames contains a non Class or null entry
+     */
+    public static List convertClassesToClassNames(List classes) {
+        if (classes == null) {
+            return null;
+        }
+        List classNames = new ArrayList(classes.size());
+        for (Iterator it = classes.iterator(); it.hasNext();) {
+            Class cls = (Class) it.next();
+            if (cls == null) {
+                classNames.add(null);
+            } else {
+                classNames.add(cls.getName());
+            }
+        }
+        return classNames;
+    }
+    
+    // Is assignable
+    // ----------------------------------------------------------------------
+    /**
+     * Checks if an array of Classes can be assigned to another array of Classes.
+     *
+     * This method calls {@link #isAssignable(Class, Class) isAssignable} for each
+     * Class pair in the input arrays. It can be used to check if a set of arguments
+     * (the first parameter) are suitably compatable with a set of method parameter types
+     * (the second parameter).
+     *
+     * Unlike the {@link Class#isAssignableFrom(java.lang.Class)} method, this
+     * method takes into account widenings of primitive classes and
+     * nulls.
+     *
+     * Primitive widenings allow an int to be assigned to a long,
+     * float or double. This method returns the correct
+     * result for these cases.
+     *
+     * Null may be assigned to any reference type. This method will
+     * return true if null is passed in and the toClass is
+     * non-primitive.
+     *
+     * Specifically, this method tests whether the type represented by the
+     * specified Class parameter can be converted to the type
+     * represented by this Class object via an identity conversion
+     * widening primitive or widening reference conversion. See 
+     * The Java Language Specification,
+     * sections 5.1.1, 5.1.2 and 5.1.4 for details.
+     *
+     * @param classArray  the array of Classes to check, may be null
+     * @param toClassArray  the array of Classes to try to assign into, may be null
+     * @return true if assignment possible
+     */
+    public static boolean isAssignable(Class[] classArray, Class[] toClassArray) {
+        if (ArrayUtils.isSameLength(classArray, toClassArray) == false) {
+            return false;
+        }
+        if (classArray == null) {
+            classArray = ArrayUtils.EMPTY_CLASS_ARRAY;
+        }
+        if (toClassArray == null) {
+            toClassArray = ArrayUtils.EMPTY_CLASS_ARRAY;
+        }
+        for (int i = 0; i < classArray.length; i++) {
+            if (isAssignable(classArray[i], toClassArray[i]) == false) {
+                return false;
+            }
+        }
+        return true;
+    }
+    
+    /**
+     * Checks if one Class can be assigned to a variable of
+     * another Class.
+     *
+     * Unlike the {@link Class#isAssignableFrom(java.lang.Class)} method,
+     * this method takes into account widenings of primitive classes and
+     * nulls.
+     *
+     * Primitive widenings allow an int to be assigned to a long, float or
+     * double. This method returns the correct result for these cases.
+     *
+     * Null may be assigned to any reference type. This method
+     * will return true if null is passed in and the
+     * toClass is non-primitive.
+     *
+     * Specifically, this method tests whether the type represented by the
+     * specified Class parameter can be converted to the type
+     * represented by this Class object via an identity conversion
+     * widening primitive or widening reference conversion. See 
+     * The Java Language Specification,
+     * sections 5.1.1, 5.1.2 and 5.1.4 for details.
+     *
+     * @param cls  the Class to check, may be null
+     * @param toClass  the Class to try to assign into, returns false if null
+     * @return true if assignment possible
+     */
+    public static boolean isAssignable(Class cls, Class toClass) {
+        if (toClass == null) {
+            return false;
+        }
+        // have to check for null, as isAssignableFrom doesn't
+        if (cls == null) {
+            return !(toClass.isPrimitive());
+        }
+        if (cls.equals(toClass)) {
+            return true;
+        }
+        if (cls.isPrimitive()) {
+            if (toClass.isPrimitive() == false) {
+                return false;
+            }
+            if (Integer.TYPE.equals(cls)) {
+                return Long.TYPE.equals(toClass) 
+                    || Float.TYPE.equals(toClass) 
+                    || Double.TYPE.equals(toClass);
+            }
+            if (Long.TYPE.equals(cls)) {
+                return Float.TYPE.equals(toClass) 
+                    || Double.TYPE.equals(toClass);
+            }
+            if (Boolean.TYPE.equals(cls)) {
+                return false;
+            }
+            if (Double.TYPE.equals(cls)) {
+                return false;
+            }
+            if (Float.TYPE.equals(cls)) {
+                return Double.TYPE.equals(toClass);
+            }
+            if (Character.TYPE.equals(cls)) {
+                return Integer.TYPE.equals(toClass) 
+                    || Long.TYPE.equals(toClass) 
+                    || Float.TYPE.equals(toClass) 
+                    || Double.TYPE.equals(toClass);
+            }
+            if (Short.TYPE.equals(cls)) {
+                return Integer.TYPE.equals(toClass) 
+                    || Long.TYPE.equals(toClass) 
+                    || Float.TYPE.equals(toClass) 
+                    || Double.TYPE.equals(toClass);
+            }
+            if (Byte.TYPE.equals(cls)) {
+                return Short.TYPE.equals(toClass) 
+                    || Integer.TYPE.equals(toClass) 
+                    || Long.TYPE.equals(toClass) 
+                    || Float.TYPE.equals(toClass) 
+                    || Double.TYPE.equals(toClass);
+            }
+            // should never get here
+            return false;
+        }
+        return toClass.isAssignableFrom(cls);
+    }
+    
+    // Inner class
+    // ----------------------------------------------------------------------
+    /**
+     * Is the specified class an inner class or static nested class.
+     * 
+     * @param cls  the class to check
+     * @return true if the class is an inner or static nested class,
+     *  false if not or null
+     */
+    public static boolean isInnerClass(Class cls) {
+        if (cls == null) {
+            return false;
+        }
+        return (cls.getName().indexOf(INNER_CLASS_SEPARATOR_CHAR) >= 0);
+    }
+    
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/Entities.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/Entities.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/Entities.java	30 Aug 2012 16:24:42 -0000	1.1
@@ -0,0 +1,702 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * Provides HTML and XML entity utilities.
+ *
+ * @see ISO Entities
+ * @see HTML 3.2 Character Entities for ISO Latin-1
+ * @see HTML 4.0 Character entity references
+ * @see HTML 4.01 Character References
+ * @see HTML 4.01 Code positions
+ *
+ * @author Alexander Day Chaffee
+ * @author Gary Gregory
+ * @since 2.0
+ * @version $Id: Entities.java,v 1.1 2012/08/30 16:24:42 marcin Exp $
+ */
+class Entities {
+
+    private static final String[][] BASIC_ARRAY = {
+        {"quot", "34"}, // " - double-quote
+        {"amp", "38"}, // & - ampersand
+        {"lt", "60"}, // < - less-than
+        {"gt", "62"}, // > - greater-than
+    };
+
+    private static final String[][] APOS_ARRAY = {
+        {"apos", "39"}, // XML apostrophe
+    };
+
+    // package scoped for testing
+    static final String[][] ISO8859_1_ARRAY = {
+        {"nbsp", "160"}, // non-breaking space
+        {"iexcl", "161"}, //inverted exclamation mark
+        {"cent", "162"}, //cent sign
+        {"pound", "163"}, //pound sign
+        {"curren", "164"}, //currency sign
+        {"yen", "165"}, //yen sign = yuan sign
+        {"brvbar", "166"}, //broken bar = broken vertical bar
+        {"sect", "167"}, //section sign
+        {"uml", "168"}, //diaeresis = spacing diaeresis
+        {"copy", "169"}, // � - copyright sign
+        {"ordf", "170"}, //feminine ordinal indicator
+        {"laquo", "171"}, //left-pointing double angle quotation mark = left pointing guillemet
+        {"not", "172"}, //not sign
+        {"shy", "173"}, //soft hyphen = discretionary hyphen
+        {"reg", "174"}, // � - registered trademark sign
+        {"macr", "175"}, //macron = spacing macron = overline = APL overbar
+        {"deg", "176"}, //degree sign
+        {"plusmn", "177"}, //plus-minus sign = plus-or-minus sign
+        {"sup2", "178"}, //superscript two = superscript digit two = squared
+        {"sup3", "179"}, //superscript three = superscript digit three = cubed
+        {"acute", "180"}, //acute accent = spacing acute
+        {"micro", "181"}, //micro sign
+        {"para", "182"}, //pilcrow sign = paragraph sign
+        {"middot", "183"}, //middle dot = Georgian comma = Greek middle dot
+        {"cedil", "184"}, //cedilla = spacing cedilla
+        {"sup1", "185"}, //superscript one = superscript digit one
+        {"ordm", "186"}, //masculine ordinal indicator
+        {"raquo", "187"}, //right-pointing double angle quotation mark = right pointing guillemet
+        {"frac14", "188"}, //vulgar fraction one quarter = fraction one quarter
+        {"frac12", "189"}, //vulgar fraction one half = fraction one half
+        {"frac34", "190"}, //vulgar fraction three quarters = fraction three quarters
+        {"iquest", "191"}, //inverted question mark = turned question mark
+        {"Agrave", "192"}, // � - uppercase A, grave accent
+        {"Aacute", "193"}, // � - uppercase A, acute accent
+        {"Acirc", "194"}, // � - uppercase A, circumflex accent
+        {"Atilde", "195"}, // � - uppercase A, tilde
+        {"Auml", "196"}, // � - uppercase A, umlaut
+        {"Aring", "197"}, // � - uppercase A, ring
+        {"AElig", "198"}, // � - uppercase AE
+        {"Ccedil", "199"}, // � - uppercase C, cedilla
+        {"Egrave", "200"}, // � - uppercase E, grave accent
+        {"Eacute", "201"}, // � - uppercase E, acute accent
+        {"Ecirc", "202"}, // � - uppercase E, circumflex accent
+        {"Euml", "203"}, // � - uppercase E, umlaut
+        {"Igrave", "204"}, // � - uppercase I, grave accent
+        {"Iacute", "205"}, // � - uppercase I, acute accent
+        {"Icirc", "206"}, // � - uppercase I, circumflex accent
+        {"Iuml", "207"}, // � - uppercase I, umlaut
+        {"ETH", "208"}, // � - uppercase Eth, Icelandic
+        {"Ntilde", "209"}, // � - uppercase N, tilde
+        {"Ograve", "210"}, // � - uppercase O, grave accent
+        {"Oacute", "211"}, // � - uppercase O, acute accent
+        {"Ocirc", "212"}, // � - uppercase O, circumflex accent
+        {"Otilde", "213"}, // � - uppercase O, tilde
+        {"Ouml", "214"}, // � - uppercase O, umlaut
+        {"times", "215"}, //multiplication sign
+        {"Oslash", "216"}, // � - uppercase O, slash
+        {"Ugrave", "217"}, // � - uppercase U, grave accent
+        {"Uacute", "218"}, // � - uppercase U, acute accent
+        {"Ucirc", "219"}, // � - uppercase U, circumflex accent
+        {"Uuml", "220"}, // � - uppercase U, umlaut
+        {"Yacute", "221"}, // � - uppercase Y, acute accent
+        {"THORN", "222"}, // � - uppercase THORN, Icelandic
+        {"szlig", "223"}, // � - lowercase sharps, German
+        {"agrave", "224"}, // � - lowercase a, grave accent
+        {"aacute", "225"}, // � - lowercase a, acute accent
+        {"acirc", "226"}, // � - lowercase a, circumflex accent
+        {"atilde", "227"}, // � - lowercase a, tilde
+        {"auml", "228"}, // � - lowercase a, umlaut
+        {"aring", "229"}, // � - lowercase a, ring
+        {"aelig", "230"}, // � - lowercase ae
+        {"ccedil", "231"}, // � - lowercase c, cedilla
+        {"egrave", "232"}, // � - lowercase e, grave accent
+        {"eacute", "233"}, // � - lowercase e, acute accent
+        {"ecirc", "234"}, // � - lowercase e, circumflex accent
+        {"euml", "235"}, // � - lowercase e, umlaut
+        {"igrave", "236"}, // � - lowercase i, grave accent
+        {"iacute", "237"}, // � - lowercase i, acute accent
+        {"icirc", "238"}, // � - lowercase i, circumflex accent
+        {"iuml", "239"}, // � - lowercase i, umlaut
+        {"eth", "240"}, // � - lowercase eth, Icelandic
+        {"ntilde", "241"}, // � - lowercase n, tilde
+        {"ograve", "242"}, // � - lowercase o, grave accent
+        {"oacute", "243"}, // � - lowercase o, acute accent
+        {"ocirc", "244"}, // � - lowercase o, circumflex accent
+        {"otilde", "245"}, // � - lowercase o, tilde
+        {"ouml", "246"}, // � - lowercase o, umlaut
+        {"divide", "247"}, // division sign
+        {"oslash", "248"}, // � - lowercase o, slash
+        {"ugrave", "249"}, // � - lowercase u, grave accent
+        {"uacute", "250"}, // � - lowercase u, acute accent
+        {"ucirc", "251"}, // � - lowercase u, circumflex accent
+        {"uuml", "252"}, // � - lowercase u, umlaut
+        {"yacute", "253"}, // � - lowercase y, acute accent
+        {"thorn", "254"}, // � - lowercase thorn, Icelandic
+        {"yuml", "255"}, // � - lowercase y, umlaut
+    };
+
+    // http://www.w3.org/TR/REC-html40/sgml/entities.html
+    // package scoped for testing
+    static final String[][] HTML40_ARRAY = {
+// 
+        {"fnof", "402"}, //latin small f with hook = function= florin, U+0192 ISOtech -->
+// 
+        {"Alpha", "913"}, //greek capital letter alpha, U+0391 -->
+        {"Beta", "914"}, //greek capital letter beta, U+0392 -->
+        {"Gamma", "915"}, //greek capital letter gamma,U+0393 ISOgrk3 -->
+        {"Delta", "916"}, //greek capital letter delta,U+0394 ISOgrk3 -->
+        {"Epsilon", "917"}, //greek capital letter epsilon, U+0395 -->
+        {"Zeta", "918"}, //greek capital letter zeta, U+0396 -->
+        {"Eta", "919"}, //greek capital letter eta, U+0397 -->
+        {"Theta", "920"}, //greek capital letter theta,U+0398 ISOgrk3 -->
+        {"Iota", "921"}, //greek capital letter iota, U+0399 -->
+        {"Kappa", "922"}, //greek capital letter kappa, U+039A -->
+        {"Lambda", "923"}, //greek capital letter lambda,U+039B ISOgrk3 -->
+        {"Mu", "924"}, //greek capital letter mu, U+039C -->
+        {"Nu", "925"}, //greek capital letter nu, U+039D -->
+        {"Xi", "926"}, //greek capital letter xi, U+039E ISOgrk3 -->
+        {"Omicron", "927"}, //greek capital letter omicron, U+039F -->
+        {"Pi", "928"}, //greek capital letter pi, U+03A0 ISOgrk3 -->
+        {"Rho", "929"}, //greek capital letter rho, U+03A1 -->
+// 
+        {"Sigma", "931"}, //greek capital letter sigma,U+03A3 ISOgrk3 -->
+        {"Tau", "932"}, //greek capital letter tau, U+03A4 -->
+        {"Upsilon", "933"}, //greek capital letter upsilon,U+03A5 ISOgrk3 -->
+        {"Phi", "934"}, //greek capital letter phi,U+03A6 ISOgrk3 -->
+        {"Chi", "935"}, //greek capital letter chi, U+03A7 -->
+        {"Psi", "936"}, //greek capital letter psi,U+03A8 ISOgrk3 -->
+        {"Omega", "937"}, //greek capital letter omega,U+03A9 ISOgrk3 -->
+        {"alpha", "945"}, //greek small letter alpha,U+03B1 ISOgrk3 -->
+        {"beta", "946"}, //greek small letter beta, U+03B2 ISOgrk3 -->
+        {"gamma", "947"}, //greek small letter gamma,U+03B3 ISOgrk3 -->
+        {"delta", "948"}, //greek small letter delta,U+03B4 ISOgrk3 -->
+        {"epsilon", "949"}, //greek small letter epsilon,U+03B5 ISOgrk3 -->
+        {"zeta", "950"}, //greek small letter zeta, U+03B6 ISOgrk3 -->
+        {"eta", "951"}, //greek small letter eta, U+03B7 ISOgrk3 -->
+        {"theta", "952"}, //greek small letter theta,U+03B8 ISOgrk3 -->
+        {"iota", "953"}, //greek small letter iota, U+03B9 ISOgrk3 -->
+        {"kappa", "954"}, //greek small letter kappa,U+03BA ISOgrk3 -->
+        {"lambda", "955"}, //greek small letter lambda,U+03BB ISOgrk3 -->
+        {"mu", "956"}, //greek small letter mu, U+03BC ISOgrk3 -->
+        {"nu", "957"}, //greek small letter nu, U+03BD ISOgrk3 -->
+        {"xi", "958"}, //greek small letter xi, U+03BE ISOgrk3 -->
+        {"omicron", "959"}, //greek small letter omicron, U+03BF NEW -->
+        {"pi", "960"}, //greek small letter pi, U+03C0 ISOgrk3 -->
+        {"rho", "961"}, //greek small letter rho, U+03C1 ISOgrk3 -->
+        {"sigmaf", "962"}, //greek small letter final sigma,U+03C2 ISOgrk3 -->
+        {"sigma", "963"}, //greek small letter sigma,U+03C3 ISOgrk3 -->
+        {"tau", "964"}, //greek small letter tau, U+03C4 ISOgrk3 -->
+        {"upsilon", "965"}, //greek small letter upsilon,U+03C5 ISOgrk3 -->
+        {"phi", "966"}, //greek small letter phi, U+03C6 ISOgrk3 -->
+        {"chi", "967"}, //greek small letter chi, U+03C7 ISOgrk3 -->
+        {"psi", "968"}, //greek small letter psi, U+03C8 ISOgrk3 -->
+        {"omega", "969"}, //greek small letter omega,U+03C9 ISOgrk3 -->
+        {"thetasym", "977"}, //greek small letter theta symbol,U+03D1 NEW -->
+        {"upsih", "978"}, //greek upsilon with hook symbol,U+03D2 NEW -->
+        {"piv", "982"}, //greek pi symbol, U+03D6 ISOgrk3 -->
+// 
+        {"bull", "8226"}, //bullet = black small circle,U+2022 ISOpub  -->
+// 
+        {"hellip", "8230"}, //horizontal ellipsis = three dot leader,U+2026 ISOpub  -->
+        {"prime", "8242"}, //prime = minutes = feet, U+2032 ISOtech -->
+        {"Prime", "8243"}, //double prime = seconds = inches,U+2033 ISOtech -->
+        {"oline", "8254"}, //overline = spacing overscore,U+203E NEW -->
+        {"frasl", "8260"}, //fraction slash, U+2044 NEW -->
+// 
+        {"weierp", "8472"}, //script capital P = power set= Weierstrass p, U+2118 ISOamso -->
+        {"image", "8465"}, //blackletter capital I = imaginary part,U+2111 ISOamso -->
+        {"real", "8476"}, //blackletter capital R = real part symbol,U+211C ISOamso -->
+        {"trade", "8482"}, //trade mark sign, U+2122 ISOnum -->
+        {"alefsym", "8501"}, //alef symbol = first transfinite cardinal,U+2135 NEW -->
+// 
+// 
+        {"larr", "8592"}, //leftwards arrow, U+2190 ISOnum -->
+        {"uarr", "8593"}, //upwards arrow, U+2191 ISOnum-->
+        {"rarr", "8594"}, //rightwards arrow, U+2192 ISOnum -->
+        {"darr", "8595"}, //downwards arrow, U+2193 ISOnum -->
+        {"harr", "8596"}, //left right arrow, U+2194 ISOamsa -->
+        {"crarr", "8629"}, //downwards arrow with corner leftwards= carriage return, U+21B5 NEW -->
+        {"lArr", "8656"}, //leftwards double arrow, U+21D0 ISOtech -->
+// 
+        {"uArr", "8657"}, //upwards double arrow, U+21D1 ISOamsa -->
+        {"rArr", "8658"}, //rightwards double arrow,U+21D2 ISOtech -->
+// 
+        {"dArr", "8659"}, //downwards double arrow, U+21D3 ISOamsa -->
+        {"hArr", "8660"}, //left right double arrow,U+21D4 ISOamsa -->
+// 
+        {"forall", "8704"}, //for all, U+2200 ISOtech -->
+        {"part", "8706"}, //partial differential, U+2202 ISOtech  -->
+        {"exist", "8707"}, //there exists, U+2203 ISOtech -->
+        {"empty", "8709"}, //empty set = null set = diameter,U+2205 ISOamso -->
+        {"nabla", "8711"}, //nabla = backward difference,U+2207 ISOtech -->
+        {"isin", "8712"}, //element of, U+2208 ISOtech -->
+        {"notin", "8713"}, //not an element of, U+2209 ISOtech -->
+        {"ni", "8715"}, //contains as member, U+220B ISOtech -->
+// 
+        {"prod", "8719"}, //n-ary product = product sign,U+220F ISOamsb -->
+// 
+        {"sum", "8721"}, //n-ary sumation, U+2211 ISOamsb -->
+// 
+        {"minus", "8722"}, //minus sign, U+2212 ISOtech -->
+        {"lowast", "8727"}, //asterisk operator, U+2217 ISOtech -->
+        {"radic", "8730"}, //square root = radical sign,U+221A ISOtech -->
+        {"prop", "8733"}, //proportional to, U+221D ISOtech -->
+        {"infin", "8734"}, //infinity, U+221E ISOtech -->
+        {"ang", "8736"}, //angle, U+2220 ISOamso -->
+        {"and", "8743"}, //logical and = wedge, U+2227 ISOtech -->
+        {"or", "8744"}, //logical or = vee, U+2228 ISOtech -->
+        {"cap", "8745"}, //intersection = cap, U+2229 ISOtech -->
+        {"cup", "8746"}, //union = cup, U+222A ISOtech -->
+        {"int", "8747"}, //integral, U+222B ISOtech -->
+        {"there4", "8756"}, //therefore, U+2234 ISOtech -->
+        {"sim", "8764"}, //tilde operator = varies with = similar to,U+223C ISOtech -->
+// 
+        {"cong", "8773"}, //approximately equal to, U+2245 ISOtech -->
+        {"asymp", "8776"}, //almost equal to = asymptotic to,U+2248 ISOamsr -->
+        {"ne", "8800"}, //not equal to, U+2260 ISOtech -->
+        {"equiv", "8801"}, //identical to, U+2261 ISOtech -->
+        {"le", "8804"}, //less-than or equal to, U+2264 ISOtech -->
+        {"ge", "8805"}, //greater-than or equal to,U+2265 ISOtech -->
+        {"sub", "8834"}, //subset of, U+2282 ISOtech -->
+        {"sup", "8835"}, //superset of, U+2283 ISOtech -->
+//  
+        {"sube", "8838"}, //subset of or equal to, U+2286 ISOtech -->
+        {"supe", "8839"}, //superset of or equal to,U+2287 ISOtech -->
+        {"oplus", "8853"}, //circled plus = direct sum,U+2295 ISOamsb -->
+        {"otimes", "8855"}, //circled times = vector product,U+2297 ISOamsb -->
+        {"perp", "8869"}, //up tack = orthogonal to = perpendicular,U+22A5 ISOtech -->
+        {"sdot", "8901"}, //dot operator, U+22C5 ISOamsb -->
+// 
+// 
+        {"lceil", "8968"}, //left ceiling = apl upstile,U+2308 ISOamsc  -->
+        {"rceil", "8969"}, //right ceiling, U+2309 ISOamsc  -->
+        {"lfloor", "8970"}, //left floor = apl downstile,U+230A ISOamsc  -->
+        {"rfloor", "8971"}, //right floor, U+230B ISOamsc  -->
+        {"lang", "9001"}, //left-pointing angle bracket = bra,U+2329 ISOtech -->
+// 
+        {"rang", "9002"}, //right-pointing angle bracket = ket,U+232A ISOtech -->
+// 
+// 
+        {"loz", "9674"}, //lozenge, U+25CA ISOpub -->
+// 
+        {"spades", "9824"}, //black spade suit, U+2660 ISOpub -->
+// 
+        {"clubs", "9827"}, //black club suit = shamrock,U+2663 ISOpub -->
+        {"hearts", "9829"}, //black heart suit = valentine,U+2665 ISOpub -->
+        {"diams", "9830"}, //black diamond suit, U+2666 ISOpub -->
+
+// 
+        {"OElig", "338"}, //  -- latin capital ligature OE,U+0152 ISOlat2 -->
+        {"oelig", "339"}, //  -- latin small ligature oe, U+0153 ISOlat2 -->
+// 
+        {"Scaron", "352"}, //  -- latin capital letter S with caron,U+0160 ISOlat2 -->
+        {"scaron", "353"}, //  -- latin small letter s with caron,U+0161 ISOlat2 -->
+        {"Yuml", "376"}, //  -- latin capital letter Y with diaeresis,U+0178 ISOlat2 -->
+// 
+        {"circ", "710"}, //  -- modifier letter circumflex accent,U+02C6 ISOpub -->
+        {"tilde", "732"}, //small tilde, U+02DC ISOdia -->
+// 
+        {"ensp", "8194"}, //en space, U+2002 ISOpub -->
+        {"emsp", "8195"}, //em space, U+2003 ISOpub -->
+        {"thinsp", "8201"}, //thin space, U+2009 ISOpub -->
+        {"zwnj", "8204"}, //zero width non-joiner,U+200C NEW RFC 2070 -->
+        {"zwj", "8205"}, //zero width joiner, U+200D NEW RFC 2070 -->
+        {"lrm", "8206"}, //left-to-right mark, U+200E NEW RFC 2070 -->
+        {"rlm", "8207"}, //right-to-left mark, U+200F NEW RFC 2070 -->
+        {"ndash", "8211"}, //en dash, U+2013 ISOpub -->
+        {"mdash", "8212"}, //em dash, U+2014 ISOpub -->
+        {"lsquo", "8216"}, //left single quotation mark,U+2018 ISOnum -->
+        {"rsquo", "8217"}, //right single quotation mark,U+2019 ISOnum -->
+        {"sbquo", "8218"}, //single low-9 quotation mark, U+201A NEW -->
+        {"ldquo", "8220"}, //left double quotation mark,U+201C ISOnum -->
+        {"rdquo", "8221"}, //right double quotation mark,U+201D ISOnum -->
+        {"bdquo", "8222"}, //double low-9 quotation mark, U+201E NEW -->
+        {"dagger", "8224"}, //dagger, U+2020 ISOpub -->
+        {"Dagger", "8225"}, //double dagger, U+2021 ISOpub -->
+        {"permil", "8240"}, //per mille sign, U+2030 ISOtech -->
+        {"lsaquo", "8249"}, //single left-pointing angle quotation mark,U+2039 ISO proposed -->
+// 
+        {"rsaquo", "8250"}, //single right-pointing angle quotation mark,U+203A ISO proposed -->
+// 
+        {"euro", "8364"}, //  -- euro sign, U+20AC NEW -->
+    };
+
+    /**
+     * The set of entities supported by standard XML.
+     */
+    public static final Entities XML;
+
+    /**
+     * The set of entities supported by HTML 3.2.
+     */
+    public static final Entities HTML32;
+
+    /**
+     * The set of entities supported by HTML 4.0.
+     */
+    public static final Entities HTML40;
+
+    static {
+        XML = new Entities();
+        XML.addEntities(BASIC_ARRAY);
+        XML.addEntities(APOS_ARRAY);
+    }
+
+    static {
+        HTML32 = new Entities();
+        HTML32.addEntities(BASIC_ARRAY);
+        HTML32.addEntities(ISO8859_1_ARRAY);
+    }
+
+    static {
+        HTML40 = new Entities();
+        fillWithHtml40Entities(HTML40);
+    }
+
+    static void fillWithHtml40Entities(Entities entities) {
+        entities.addEntities(BASIC_ARRAY);
+        entities.addEntities(ISO8859_1_ARRAY);
+        entities.addEntities(HTML40_ARRAY);
+    }
+
+    static interface EntityMap {
+        void add(String name, int value);
+
+        String name(int value);
+
+        int value(String name);
+    }
+
+    static class PrimitiveEntityMap implements EntityMap {
+        private Map mapNameToValue = new HashMap();
+        private IntHashMap mapValueToName = new IntHashMap();
+
+        public void add(String name, int value) {
+            mapNameToValue.put(name, new Integer(value));
+            mapValueToName.put(value, name);
+        }
+
+        public String name(int value) {
+            return (String) mapValueToName.get(value);
+        }
+
+        public int value(String name) {
+            Object value = mapNameToValue.get(name);
+            if (value == null)
+                return -1;
+            return ((Integer) value).intValue();
+        }
+    }
+
+
+    static abstract class MapIntMap implements Entities.EntityMap {
+        protected Map mapNameToValue;
+        protected Map mapValueToName;
+
+        public void add(String name, int value) {
+            mapNameToValue.put(name, new Integer(value));
+            mapValueToName.put(new Integer(value), name);
+        }
+
+        public String name(int value) {
+            return (String) mapValueToName.get(new Integer(value));
+        }
+
+        public int value(String name) {
+            Object value = mapNameToValue.get(name);
+            if (value == null)
+                return -1;
+            return ((Integer) value).intValue();
+        }
+    }
+
+    static class HashEntityMap extends MapIntMap {
+        public HashEntityMap() {
+            mapNameToValue = new HashMap();
+            mapValueToName = new HashMap();
+        }
+    }
+
+    static class TreeEntityMap extends MapIntMap {
+        public TreeEntityMap() {
+            mapNameToValue = new TreeMap();
+            mapValueToName = new TreeMap();
+        }
+    }
+
+    static class LookupEntityMap extends PrimitiveEntityMap {
+        private String[] lookupTable;
+        private int LOOKUP_TABLE_SIZE = 256;
+
+        public String name(int value) {
+            if (value < LOOKUP_TABLE_SIZE) {
+                return lookupTable()[value];
+            }
+            return super.name(value);
+        }
+
+        private String[] lookupTable() {
+            if (lookupTable == null) {
+                createLookupTable();
+            }
+            return lookupTable;
+        }
+
+        private void createLookupTable() {
+            lookupTable = new String[LOOKUP_TABLE_SIZE];
+            for (int i = 0; i < LOOKUP_TABLE_SIZE; ++i) {
+                lookupTable[i] = super.name(i);
+            }
+        }
+    }
+
+    static class ArrayEntityMap implements EntityMap {
+        protected int growBy = 100;
+        protected int size = 0;
+        protected String[] names;
+        protected int[] values;
+
+        public ArrayEntityMap() {
+            names = new String[growBy];
+            values = new int[growBy];
+        }
+
+        public ArrayEntityMap(int growBy) {
+            this.growBy = growBy;
+            names = new String[growBy];
+            values = new int[growBy];
+        }
+
+        public void add(String name, int value) {
+            ensureCapacity(size + 1);
+            names[size] = name;
+            values[size] = value;
+            size++;
+        }
+
+        protected void ensureCapacity(int capacity) {
+            if (capacity > names.length) {
+                int newSize = Math.max(capacity, size + growBy);
+                String[] newNames = new String[newSize];
+                System.arraycopy(names, 0, newNames, 0, size);
+                names = newNames;
+                int[] newValues = new int[newSize];
+                System.arraycopy(values, 0, newValues, 0, size);
+                values = newValues;
+            }
+        }
+
+        public String name(int value) {
+            for (int i = 0; i < size; ++i) {
+                if (values[i] == value) {
+                    return names[i];
+                }
+            }
+            return null;
+        }
+
+        public int value(String name) {
+            for (int i = 0; i < size; ++i) {
+                if (names[i].equals(name)) {
+                    return values[i];
+                }
+            }
+            return -1;
+        }
+    }
+
+    static class BinaryEntityMap extends ArrayEntityMap {
+
+        public BinaryEntityMap() {
+        }
+
+        public BinaryEntityMap(int growBy) {
+            super(growBy);
+        }
+
+        // based on code in java.util.Arrays
+        private int binarySearch(int key) {
+            int low = 0;
+            int high = size - 1;
+
+            while (low <= high) {
+                int mid = (low + high) >> 1;
+                int midVal = values[mid];
+
+                if (midVal < key)
+                    low = mid + 1;
+                else if (midVal > key)
+                    high = mid - 1;
+                else
+                    return mid; // key found
+            }
+            return -(low + 1);  // key not found.
+        }
+
+        public void add(String name, int value) {
+            ensureCapacity(size + 1);
+            int insertAt = binarySearch(value);
+            if (insertAt > 0) return;    // note: this means you can't insert the same value twice
+            insertAt = -(insertAt + 1);  // binarySearch returns it negative and off-by-one
+            System.arraycopy(values, insertAt, values, insertAt + 1, size - insertAt);
+            values[insertAt] = value;
+            System.arraycopy(names, insertAt, names, insertAt + 1, size - insertAt);
+            names[insertAt] = name;
+            size++;
+        }
+
+        public String name(int value) {
+            int index = binarySearch(value);
+            if (index < 0) return null;
+            return names[index];
+        }
+    }
+
+    // package scoped for testing
+    EntityMap map = new Entities.LookupEntityMap();
+
+    public void addEntities(String[][] entityArray) {
+        for (int i = 0; i < entityArray.length; ++i) {
+            addEntity(entityArray[i][0], Integer.parseInt(entityArray[i][1]));
+        }
+    }
+
+    public void addEntity(String name, int value) {
+        map.add(name, value);
+    }
+
+    public String entityName(int value) {
+        return map.name(value);
+    }
+
+
+    public int entityValue(String name) {
+        return map.value(name);
+    }
+
+    /**
+     * Escapes the characters in a String.
+     *
+     * For example, if you have called addEntity("foo", 0xA1),
+     * escape("\u00A1") will return "&foo;"
+     *
+     * @param str The String to escape.
+     * @return A new escaped String.
+     */
+    public String escape(String str) {
+        //todo: rewrite to use a Writer
+        StringBuffer buf = new StringBuffer(str.length() * 2);
+        int i;
+        for (i = 0; i < str.length(); ++i) {
+            char ch = str.charAt(i);
+            String entityName = this.entityName(ch);
+            if (entityName == null) {
+                if (ch > 0x7F) {
+                    int intValue = ch;
+                    buf.append("");
+                    buf.append(intValue);
+                    buf.append(';');
+                } else {
+                    buf.append(ch);
+                }
+            } else {
+                buf.append('&');
+                buf.append(entityName);
+                buf.append(';');
+            }
+        }
+        return buf.toString();
+    }
+
+    /**
+     * Unescapes the entities in a String.
+     *
+     * For example, if you have called addEntity("foo", 0xA1),
+     * unescape("&foo;") will return "\u00A1"
+     *
+     * @param str The String to escape.
+     * @return A new escaped String.
+     */
+    public String unescape(String str) {
+        StringBuffer buf = new StringBuffer(str.length());
+        int i;
+        for (i = 0; i < str.length(); ++i) {
+            char ch = str.charAt(i);
+            if (ch == '&') {
+                int semi = str.indexOf(';', i + 1);
+                if (semi == -1) {
+                    buf.append(ch);
+                    continue;
+                }
+                String entityName = str.substring(i + 1, semi);
+                int entityValue;
+                if (entityName.charAt(0) == '#') {
+                    entityValue = Integer.parseInt(entityName.substring(1));
+                } else {
+                    entityValue = this.entityValue(entityName);
+                }
+                if (entityValue == -1) {
+                    buf.append('&');
+                    buf.append(entityName);
+                    buf.append(';');
+                } else {
+                    buf.append((char) (entityValue));
+                }
+                i = semi;
+            } else {
+                buf.append(ch);
+            }
+        }
+        return buf.toString();
+    }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/IllegalClassException.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/IllegalClassException.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/IllegalClassException.java	30 Aug 2012 16:24:42 -0000	1.1
@@ -0,0 +1,100 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang;
+
+/**
+ * Thrown when an object is an instance of an unexpected type (a class or interface).
+ * 
+ * @author Matthew Hawthorne
+ * @author Gary Gregory
+ * @since 2.0
+ * @version $Id: IllegalClassException.java,v 1.1 2012/08/30 16:24:42 marcin Exp $
+ */
+public class IllegalClassException extends IllegalArgumentException {
+
+    /**
+     * Instantiates with the specified types (classes or interfaces).
+     * 
+     * @param expected  the expected type
+     * @param actual  the actual type
+     */
+    public IllegalClassException(Class expected, Class actual) {
+        super(
+            "Expected: "
+                + safeGetClassName(expected)
+                + ", actual: "
+                + safeGetClassName(actual));
+    }
+
+    /**
+     * Instantiates with the specified message.
+     * 
+     * @param message  the exception message
+     */
+    public IllegalClassException(String message) {
+        super(message);
+    }
+
+    /**
+     * Returns the class name or null if the class is
+     * null.
+     * 
+     * @param cls  a Class
+     * @return the name of cls, or null if if cls is null.
+     */
+    private static final String safeGetClassName(Class cls) {
+        return cls == null ? null : cls.getName();
+    }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/IncompleteArgumentException.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/IncompleteArgumentException.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/IncompleteArgumentException.java	30 Aug 2012 16:24:42 -0000	1.1
@@ -0,0 +1,99 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang;
+
+import java.util.Arrays;
+
+/**
+ * Thrown to indicate an incomplete argument to a method.
+ * 
+ * @author Matthew Hawthorne
+ * @since 2.0
+ * @version $Id: IncompleteArgumentException.java,v 1.1 2012/08/30 16:24:42 marcin Exp $
+ */
+public class IncompleteArgumentException extends IllegalArgumentException {
+
+    /**
+     * Instantiates with the specified description.
+     * 
+     * @param argName  a description of the incomplete argument
+     */
+    public IncompleteArgumentException(String argName) {
+        super(argName + " is incomplete.");
+    }
+
+    /**
+     * Instantiates with the specified description.
+     * 
+     * @param argName  a description of the incomplete argument
+     * @param items  an array describing the arguments missing
+     */
+    public IncompleteArgumentException(String argName, String[] items) {
+        super(
+            argName
+                + " is missing the following items: "
+                + safeArrayToString(items));
+    }
+
+    /**
+     * 7Converts an array to a string without throwing an exception.
+     * 
+     * @param array  an array
+     * @return the array as a string
+     */
+    private static final String safeArrayToString(Object[] array) {
+        return array == null ? null : Arrays.asList(array).toString();
+    }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/IntHashMap.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/IntHashMap.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/IntHashMap.java	30 Aug 2012 16:24:42 -0000	1.1
@@ -0,0 +1,400 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+
+/*
+ * Note: originally released under the GNU LGPL v2.1, 
+ * but rereleased by the original author under the ASF license (above).
+ */
+package org.apache.commons.lang;
+
+/**
+ * A hash map that uses primitive ints for the key rather than objects.
+ *
+ * Note that this class is for internal optimization purposes only, and may
+ * not be supported in future releases of Jakarta Commons Lang.  Utilities of
+ * this sort may be included in future releases of Jakarta Commons Collections.
+ *
+ * @author Justin Couch
+ * @author Alex Chaffee (alex@apache.org)
+ * @author Stephen Colebourne
+ * @since 2.0
+ * @version $Revision: 1.1 $
+ * @see java.util.HashMap
+ */
+class IntHashMap {
+
+    /**
+     * The hash table data.
+     */
+    private transient Entry table[];
+
+    /**
+     * The total number of entries in the hash table.
+     */
+    private transient int count;
+
+    /**
+     * The table is rehashed when its size exceeds this threshold.  (The
+     * value of this field is (int)(capacity * loadFactor).)
+     *
+     * @serial
+     */
+    private int threshold;
+
+    /**
+     * The load factor for the hashtable.
+     *
+     * @serial
+     */
+    private float loadFactor;
+
+    /**
+     * Innerclass that acts as a datastructure to create a new entry in the
+     * table.
+     */
+    private static class Entry {
+        int hash;
+        int key;
+        Object value;
+        Entry next;
+
+        /**
+         * Create a new entry with the given values.
+         *
+         * @param hash The code used to hash the object with
+         * @param key The key used to enter this in the table
+         * @param value The value for this key
+         * @param next A reference to the next entry in the table
+         */
+        protected Entry(int hash, int key, Object value, Entry next) {
+            this.hash = hash;
+            this.key = key;
+            this.value = value;
+            this.next = next;
+        }
+    }
+
+    /**
+     * Constructs a new, empty hashtable with a default capacity and load
+     * factor, which is 20 and 0.75 respectively.
+     */
+    public IntHashMap() {
+        this(20, 0.75f);
+    }
+
+    /**
+     * Constructs a new, empty hashtable with the specified initial capacity
+     * and default load factor, which is 0.75.
+     *
+     * @param  initialCapacity the initial capacity of the hashtable.
+     * @throws IllegalArgumentException if the initial capacity is less
+     *   than zero.
+     */
+    public IntHashMap(int initialCapacity) {
+        this(initialCapacity, 0.75f);
+    }
+
+    /**
+     * Constructs a new, empty hashtable with the specified initial
+     * capacity and the specified load factor.
+     *
+     * @param initialCapacity the initial capacity of the hashtable.
+     * @param loadFactor the load factor of the hashtable.
+     * @throws IllegalArgumentException  if the initial capacity is less
+     *             than zero, or if the load factor is nonpositive.
+     */
+    public IntHashMap(int initialCapacity, float loadFactor) {
+        super();
+        if (initialCapacity < 0) {
+            throw new IllegalArgumentException("Illegal Capacity: " + initialCapacity);
+        }
+        if (loadFactor <= 0) {
+            throw new IllegalArgumentException("Illegal Load: " + loadFactor);
+        }
+        if (initialCapacity == 0) {
+            initialCapacity = 1;
+        }
+
+        this.loadFactor = loadFactor;
+        table = new Entry[initialCapacity];
+        threshold = (int) (initialCapacity * loadFactor);
+    }
+
+    /**
+     * Returns the number of keys in this hashtable.
+     *
+     * @return  the number of keys in this hashtable.
+     */
+    public int size() {
+        return count;
+    }
+
+    /**
+     * Tests if this hashtable maps no keys to values.
+     *
+     * @return  true if this hashtable maps no keys to values;
+     *          false otherwise.
+     */
+    public boolean isEmpty() {
+        return count == 0;
+    }
+
+    /**
+     * Tests if some key maps into the specified value in this hashtable.
+     * This operation is more expensive than the containsKey
+     * method.
+     *
+     * Note that this method is identical in functionality to containsValue,
+     * (which is part of the Map interface in the collections framework).
+     *
+     * @param      value   a value to search for.
+     * @return     true if and only if some key maps to the
+     *             value argument in this hashtable as
+     *             determined by the equals method;
+     *             false otherwise.
+     * @throws  NullPointerException  if the value is null.
+     * @see        #containsKey(int)
+     * @see        #containsValue(Object)
+     * @see        java.util.Map
+     */
+    public boolean contains(Object value) {
+        if (value == null) {
+            throw new NullPointerException();
+        }
+
+        Entry tab[] = table;
+        for (int i = tab.length; i-- > 0;) {
+            for (Entry e = tab[i]; e != null; e = e.next) {
+                if (e.value.equals(value)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Returns true if this HashMap maps one or more keys
+     * to this value.
+     *
+     * Note that this method is identical in functionality to contains
+     * (which predates the Map interface).
+     *
+     * @param value value whose presence in this HashMap is to be tested.
+     * @see    java.util.Map
+     * @since JDK1.2
+     */
+    public boolean containsValue(Object value) {
+        return contains(value);
+    }
+
+    /**
+     * Tests if the specified object is a key in this hashtable.
+     *
+     * @param  key  possible key.
+     * @return true if and only if the specified object is a
+     *    key in this hashtable, as determined by the equals
+     *    method; false otherwise.
+     * @see #contains(Object)
+     */
+    public boolean containsKey(int key) {
+        Entry tab[] = table;
+        int hash = key;
+        int index = (hash & 0x7FFFFFFF) % tab.length;
+        for (Entry e = tab[index]; e != null; e = e.next) {
+            if (e.hash == hash) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Returns the value to which the specified key is mapped in this map.
+     *
+     * @param   key   a key in the hashtable.
+     * @return  the value to which the key is mapped in this hashtable;
+     *          null if the key is not mapped to any value in
+     *          this hashtable.
+     * @see     #put(int, Object)
+     */
+    public Object get(int key) {
+        Entry tab[] = table;
+        int hash = key;
+        int index = (hash & 0x7FFFFFFF) % tab.length;
+        for (Entry e = tab[index]; e != null; e = e.next) {
+            if (e.hash == hash) {
+                return e.value;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Increases the capacity of and internally reorganizes this
+     * hashtable, in order to accommodate and access its entries more
+     * efficiently.
+     *
+     * This method is called automatically when the number of keys
+     * in the hashtable exceeds this hashtable's capacity and load
+     * factor.
+     */
+    protected void rehash() {
+        int oldCapacity = table.length;
+        Entry oldMap[] = table;
+
+        int newCapacity = oldCapacity * 2 + 1;
+        Entry newMap[] = new Entry[newCapacity];
+
+        threshold = (int) (newCapacity * loadFactor);
+        table = newMap;
+
+        for (int i = oldCapacity; i-- > 0;) {
+            for (Entry old = oldMap[i]; old != null;) {
+                Entry e = old;
+                old = old.next;
+
+                int index = (e.hash & 0x7FFFFFFF) % newCapacity;
+                e.next = newMap[index];
+                newMap[index] = e;
+            }
+        }
+    }
+
+    /**
+     * Maps the specified key to the specified
+     * value in this hashtable. The key cannot be
+     * null. 
+     *
+     * The value can be retrieved by calling the get method
+     * with a key that is equal to the original key.
+     *
+     * @param key     the hashtable key.
+     * @param value   the value.
+     * @return the previous value of the specified key in this hashtable,
+     *         or null if it did not have one.
+     * @throws  NullPointerException  if the key is null.
+     * @see     #get(int)
+     */
+    public Object put(int key, Object value) {
+        // Makes sure the key is not already in the hashtable.
+        Entry tab[] = table;
+        int hash = key;
+        int index = (hash & 0x7FFFFFFF) % tab.length;
+        for (Entry e = tab[index]; e != null; e = e.next) {
+            if (e.hash == hash) {
+                Object old = e.value;
+                e.value = value;
+                return old;
+            }
+        }
+
+        if (count >= threshold) {
+            // Rehash the table if the threshold is exceeded
+            rehash();
+
+            tab = table;
+            index = (hash & 0x7FFFFFFF) % tab.length;
+        }
+
+        // Creates the new entry.
+        Entry e = new Entry(hash, key, value, tab[index]);
+        tab[index] = e;
+        count++;
+        return null;
+    }
+
+    /**
+     * Removes the key (and its corresponding value) from this
+     * hashtable.
+     *
+     * This method does nothing if the key is not present in the
+     * hashtable.
+     *
+     * @param   key   the key that needs to be removed.
+     * @return  the value to which the key had been mapped in this hashtable,
+     *          or null if the key did not have a mapping.
+     */
+    public Object remove(int key) {
+        Entry tab[] = table;
+        int hash = key;
+        int index = (hash & 0x7FFFFFFF) % tab.length;
+        for (Entry e = tab[index], prev = null; e != null; prev = e, e = e.next) {
+            if (e.hash == hash) {
+                if (prev != null) {
+                    prev.next = e.next;
+                } else {
+                    tab[index] = e.next;
+                }
+                count--;
+                Object oldValue = e.value;
+                e.value = null;
+                return oldValue;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Clears this hashtable so that it contains no keys.
+     */
+    public synchronized void clear() {
+        Entry tab[] = table;
+        for (int index = tab.length; --index >= 0;) {
+            tab[index] = null;
+        }
+        count = 0;
+    }
+    
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/NotImplementedException.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/NotImplementedException.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/NotImplementedException.java	30 Aug 2012 16:24:42 -0000	1.1
@@ -0,0 +1,85 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang;
+
+/**
+ * Thrown to indicate that a method has not been implemented.
+ * 
+ * @author Matthew Hawthorne
+ * @since 2.0
+ * @version $Id: NotImplementedException.java,v 1.1 2012/08/30 16:24:42 marcin Exp $
+ */
+public class NotImplementedException extends UnsupportedOperationException {
+
+    /**
+     * Constructes the exception with the specified class.
+     * 
+     * @param clazz  the Class that has not implemented the method
+     */
+    public NotImplementedException(Class clazz) {
+        super(
+            "Method is not implemented in class "
+                + ((clazz == null) ? null : clazz.getName()));
+    }
+
+    /**
+     * Constructs the exception with the specified message.
+     * 
+     * @param msg  the exception message.
+     */
+    public NotImplementedException(String msg) {
+        super(msg);
+    }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/NullArgumentException.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/NullArgumentException.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/NullArgumentException.java	30 Aug 2012 16:24:42 -0000	1.1
@@ -0,0 +1,76 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang;
+
+/**
+ * Thrown to indicate that an argument was null and should
+ * not have been.
+ * 
+ * @author Matthew Hawthorne
+ * @author Stephen Colebourne
+ * @since 2.0
+ * @version $Id: NullArgumentException.java,v 1.1 2012/08/30 16:24:42 marcin Exp $
+ */
+public class NullArgumentException extends IllegalArgumentException {
+
+	/**
+	 * Instantiates with the given argument name.
+     * 
+	 * @param argName  the name of the argument that was null.
+	 */
+	public NullArgumentException(String argName) {
+		super(argName + " must not be null.");
+	}
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/NumberRange.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/NumberRange.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/NumberRange.java	30 Aug 2012 16:24:42 -0000	1.1
@@ -0,0 +1,257 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang;
+
+/**
+ * Represents a range of {@link Number} objects.
+ * 
+ * This class uses double comparisons. This means that it
+ * is unsuitable for dealing with large Long, BigDecimal
+ * or BigInteger numbers.
+ *
+ * @author Christopher Elkins
+ * @author Stephen Colebourne
+ * @since 1.0
+ * @version $Revision: 1.1 $ $Date: 2012/08/30 16:24:42 $
+ * 
+ * @deprecated Use one of the Range classes in org.apache.commons.lang.math.
+ *             Class will be removed in Commons Lang 3.0.
+ * 
+ */
+public final class NumberRange {
+
+    /* The minimum number in this range. */
+    private final Number min;
+
+    /* The maximum number in this range. */
+    private final Number max;
+
+
+    /**
+     * Constructs a new NumberRange using
+     * number as both the minimum and maximum in
+     * this range.
+     *
+     * @param num the number to use for this range
+     * @throws NullPointerException if the number is null
+     */
+    public NumberRange(Number num) {
+        if (num == null) {
+            throw new NullPointerException("The number must not be null");
+        }
+
+        this.min = num;
+        this.max = num;
+    }
+
+    /**
+     * Constructs a new NumberRange with the specified
+     * minimum and maximum numbers.
+     * 
+     * If the maximum is less than the minimum, the range will be constructed
+     * from the minimum value to the minimum value, not what you would expect!.
+     *
+     * @param min the minimum number in this range
+     * @param max the maximum number in this range
+     * @throws NullPointerException if either the minimum or maximum number is
+     *  null
+     */
+    public NumberRange(Number min, Number max) {
+        if (min == null) {
+            throw new NullPointerException("The minimum value must not be null");
+        } else if (max == null) {
+            throw new NullPointerException("The maximum value must not be null");
+        }
+
+        if (max.doubleValue() < min.doubleValue()) {
+            this.min = this.max = min;
+        } else {
+            this.min = min;
+            this.max = max;
+        }
+    }
+
+    /**
+     * Returns the minimum number in this range.
+     *
+     * @return the minimum number in this range
+     */
+    public Number getMinimum() {
+        return min;
+    }
+
+    /**
+     * Returns the maximum number in this range.
+     *
+     * @return the maximum number in this range
+     */
+    public Number getMaximum() {
+        return max;
+    }
+
+    /**
+     * Tests whether the specified number occurs within
+     * this range using double comparison.
+     *
+     * @param number the number to test
+     * @return true if the specified number occurs within this
+     *  range; otherwise, false
+     */
+    public boolean includesNumber(Number number) {
+        if (number == null) {
+            return false;
+        } else {
+            return !(min.doubleValue() > number.doubleValue()) &&
+                !(max.doubleValue() < number.doubleValue());
+        }
+    }
+
+    /**
+     * Tests whether the specified range occurs entirely within this
+     * range using double comparison.
+     *
+     * @param range the range to test
+     * @return true if the specified range occurs entirely within
+     *  this range; otherwise, false
+     */
+    public boolean includesRange(NumberRange range) {
+        if (range == null) {
+            return false;
+        } else {
+            return includesNumber(range.min) && includesNumber(range.max);
+        }
+    }
+
+    /**
+     * Tests whether the specified range overlaps with this range
+     * using double comparison.
+     *
+     * @param range the range to test
+     * @return true if the specified range overlaps with this
+     *  range; otherwise, false
+     */
+    public boolean overlaps(NumberRange range) {
+        if (range == null) {
+            return false;
+        } else {
+            return range.includesNumber(min) || range.includesNumber(max) || 
+                includesRange(range);
+        }
+    }
+
+    /**
+     * Indicates whether some other Object is
+     * "equal" to this one.
+     *
+     * @param obj the reference object with which to compare
+     * @return true if this object is the same as the obj
+     *  argument; false otherwise
+     */
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        } else if (!(obj instanceof NumberRange)) {
+            return false;
+        } else {
+            NumberRange range = (NumberRange)obj;
+            return min.equals(range.min) && max.equals(range.max);
+        }
+    }
+
+    /**
+     * Returns a hash code value for this object.
+     *
+     * @return a hash code value for this object
+     */
+    public int hashCode() {
+        int result = 17;
+        result = 37 * result + min.hashCode();
+        result = 37 * result + max.hashCode();
+        return result;
+    }
+
+    /**
+     * Returns the string representation of this range.
+     *
+     * This string is the string representation of the minimum and
+     * maximum numbers in the range, separated by a hyphen. If a number
+     * is negative, then it is enclosed in parentheses.
+     *
+     * @return the string representation of this range
+     */
+    public String toString() {
+        StringBuffer sb = new StringBuffer();
+
+        if (min.doubleValue() < 0) {
+            sb.append('(')
+                .append(min)
+                .append(')');
+        } else {
+            sb.append(min);
+        }
+
+        sb.append('-');
+
+        if (max.doubleValue() < 0) {
+            sb.append('(')
+                .append(max)
+                .append(')');
+        } else {
+            sb.append(max);
+        }
+
+        return sb.toString();
+    }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/NumberUtils.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/NumberUtils.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/NumberUtils.java	30 Aug 2012 16:24:42 -0000	1.1
@@ -0,0 +1,743 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+/**
+ * Provides extra functionality for Java Number classes.
+ *
+ * @author Henri Yandell
+ * @author Rand McNeely
+ * @author Stephen Colebourne
+ * @author Steve Downey
+ * @author Eric Pugh
+ * @author Phil Steitz
+ * @since 1.0
+ * @version $Id: NumberUtils.java,v 1.1 2012/08/30 16:24:42 marcin Exp $
+ * 
+ * @deprecated Moved to org.apache.commons.lang.math.
+ *             Class will be removed in Commons Lang 3.0.
+ */
+public final class NumberUtils {
+    // DEPRECATED CLASS !!!
+    
+    /**
+     * NumberUtils instances should NOT be constructed in standard programming.
+     * Instead, the class should be used as NumberUtils.stringToInt("6");.
+     *
+     * This constructor is public to permit tools that require a JavaBean instance
+     * to operate.
+     */
+    public NumberUtils() {
+    }
+
+    //--------------------------------------------------------------------
+    
+    /**
+     * Convert a String to an int, returning
+     * zero if the conversion fails.
+     * 
+     * @param str  the string to convert
+     * @return the int represented by the string, or zero if
+     *  conversion fails
+     */
+    public static int stringToInt(String str) {
+        return stringToInt(str, 0);
+    }
+
+    /**
+     * Convert a String to an int, returning a
+     * default value if the conversion fails.
+     * 
+     * @param str  the string to convert
+     * @param defaultValue  the default value
+     * @return the int represented by the string, or the default if conversion fails
+     */
+    public static int stringToInt(String str, int defaultValue) {
+        try {
+            return Integer.parseInt(str);
+        } catch (NumberFormatException nfe) {
+            return defaultValue;
+        }
+    }
+
+    //--------------------------------------------------------------------
+    
+    // must handle Long, Float, Integer, Float, Short,
+    //                  BigDecimal, BigInteger and Byte
+    // useful methods:
+    // Byte.decode(String)
+    // Byte.valueOf(String,int radix)
+    // Byte.valueOf(String)
+    // Double.valueOf(String)
+    // Float.valueOf(String)
+    // new Float(String)
+    // Integer.valueOf(String,int radix)
+    // Integer.valueOf(String)
+    // Integer.decode(String)
+    // Integer.getInteger(String)
+    // Integer.getInteger(String,int val)
+    // Integer.getInteger(String,Integer val)
+    // new Integer(String)
+    // new Double(String)
+    // new Byte(String)
+    // new Long(String)
+    // Long.getLong(String)
+    // Long.getLong(String,int)
+    // Long.getLong(String,Integer)
+    // Long.valueOf(String,int)
+    // Long.valueOf(String)
+    // new Short(String)
+    // Short.decode(String)
+    // Short.valueOf(String,int)
+    // Short.valueOf(String)
+    // new BigDecimal(String)
+    // new BigInteger(String)
+    // new BigInteger(String,int radix)
+    // Possible inputs:
+    // 45 45.5 45E7 4.5E7 Hex Oct Binary xxxF xxxD xxxf xxxd
+    // plus minus everything. Prolly more. A lot are not separable.
+
+    /**
+     * Turns a string value into a java.lang.Number.
+     *
+     * First, the value is examined for a type qualifier on the end
+     * ('f','F','d','D','l','L').  If it is found, it starts 
+     * trying to create succissively larger types from the type specified
+     * until one is found that can hold the value.
+     *
+     * If a type specifier is not found, it will check for a decimal point
+     * and then try successively larger types from Integer to
+     * BigInteger and from Float to
+     * BigDecimal.
+     *
+     * If the string starts with 0x or -0x, it
+     * will be interpreted as a hexadecimal integer.  Values with leading
+     * 0's will not be interpreted as octal.
+     *
+     * @param val String containing a number
+     * @return Number created from the string
+     * @throws NumberFormatException if the value cannot be converted
+     */
+    public static Number createNumber(String val) throws NumberFormatException {
+        if (val == null) {
+            return null;
+        }
+        if (val.length() == 0) {
+            throw new NumberFormatException("\"\" is not a valid number.");
+        }
+        if (val.startsWith("--")) {
+            // this is protection for poorness in java.lang.BigDecimal.
+            // it accepts this as a legal value, but it does not appear 
+            // to be in specification of class. OS X Java parses it to 
+            // a wrong value.
+            return null;
+        }
+        if (val.startsWith("0x") || val.startsWith("-0x")) {
+            return createInteger(val);
+        }   
+        char lastChar = val.charAt(val.length() - 1);
+        String mant;
+        String dec;
+        String exp;
+        int decPos = val.indexOf('.');
+        int expPos = val.indexOf('e') + val.indexOf('E') + 1;
+
+        if (decPos > -1) {
+
+            if (expPos > -1) {
+                if (expPos < decPos) {
+                    throw new NumberFormatException(val + " is not a valid number.");
+                }
+                dec = val.substring(decPos + 1, expPos);
+            } else {
+                dec = val.substring(decPos + 1);
+            }
+            mant = val.substring(0, decPos);
+        } else {
+            if (expPos > -1) {
+                mant = val.substring(0, expPos);
+            } else {
+                mant = val;
+            }
+            dec = null;
+        }
+        if (!Character.isDigit(lastChar)) {
+            if (expPos > -1 && expPos < val.length() - 1) {
+                exp = val.substring(expPos + 1, val.length() - 1);
+            } else {
+                exp = null;
+            }
+            //Requesting a specific type..
+            String numeric = val.substring(0, val.length() - 1);
+            boolean allZeros = isAllZeros(mant) && isAllZeros(exp);
+            switch (lastChar) {
+                case 'l' :
+                case 'L' :
+                    if (dec == null
+                        && exp == null
+                        && isDigits(numeric.substring(1))
+                        && (numeric.charAt(0) == '-' || Character.isDigit(numeric.charAt(0)))) {
+                        try {
+                            return createLong(numeric);
+                        } catch (NumberFormatException nfe) {
+                            //Too big for a long
+                        }
+                        return createBigInteger(numeric);
+
+                    }
+                    throw new NumberFormatException(val + " is not a valid number.");
+                case 'f' :
+                case 'F' :
+                    try {
+                        Float f = NumberUtils.createFloat(numeric);
+                        if (!(f.isInfinite() || (f.floatValue() == 0.0F && !allZeros))) {
+                            //If it's too big for a float or the float value = 0 and the string
+                            //has non-zeros in it, then float doens't have the presision we want
+                            return f;
+                        }
+
+                    } catch (NumberFormatException nfe) {
+                    }
+                    //Fall through
+                case 'd' :
+                case 'D' :
+                    try {
+                        Double d = NumberUtils.createDouble(numeric);
+                        if (!(d.isInfinite() || (d.floatValue() == 0.0D && !allZeros))) {
+                            return d;
+                        }
+                    } catch (NumberFormatException nfe) {
+                    }
+                    try {
+                        return createBigDecimal(numeric);
+                    } catch (NumberFormatException e) {
+                    }
+                    //Fall through
+                default :
+                    throw new NumberFormatException(val + " is not a valid number.");
+
+            }
+        } else {
+            //User doesn't have a preference on the return type, so let's start
+            //small and go from there...
+            if (expPos > -1 && expPos < val.length() - 1) {
+                exp = val.substring(expPos + 1, val.length());
+            } else {
+                exp = null;
+            }
+            if (dec == null && exp == null) {
+                //Must be an int,long,bigint
+                try {
+                    return createInteger(val);
+                } catch (NumberFormatException nfe) {
+                }
+                try {
+                    return createLong(val);
+                } catch (NumberFormatException nfe) {
+                }
+                return createBigInteger(val);
+
+            } else {
+                //Must be a float,double,BigDec
+                boolean allZeros = isAllZeros(mant) && isAllZeros(exp);
+                try {
+                    Float f = createFloat(val);
+                    if (!(f.isInfinite() || (f.floatValue() == 0.0F && !allZeros))) {
+                        return f;
+                    }
+                } catch (NumberFormatException nfe) {
+                }
+                try {
+                    Double d = createDouble(val);
+                    if (!(d.isInfinite() || (d.doubleValue() == 0.0D && !allZeros))) {
+                        return d;
+                    }
+                } catch (NumberFormatException nfe) {
+                }
+
+                return createBigDecimal(val);
+
+            }
+
+        }
+    }
+
+    /**
+     * Utility method for {@link #createNumber(java.lang.String)}.
+     *
+     * Returns true if s is null.
+     * 
+     * @param s the String to check
+     * @return if it is all zeros or null
+     */
+    private static boolean isAllZeros(String s) {
+        if (s == null) {
+            return true;
+        }
+        for (int i = s.length() - 1; i >= 0; i--) {
+            if (s.charAt(i) != '0') {
+                return false;
+            }
+        }
+        return s.length() > 0;
+    }
+
+    //--------------------------------------------------------------------
+    
+    /**
+     * Convert a String to a Float.
+     * 
+     * @param val  a String to convert
+     * @return converted Float
+     * @throws NumberFormatException if the value cannot be converted
+     */
+    public static Float createFloat(String val) {
+        return Float.valueOf(val);
+    }
+
+    /**
+     * Convert a String to a Double.
+     * 
+     * @param val  a String to convert
+     * @return converted Double
+     * @throws NumberFormatException if the value cannot be converted
+     */
+    public static Double createDouble(String val) {
+        return Double.valueOf(val);
+    }
+
+    /**
+     * Convert a String to a Integer, handling
+     * hex and octal notations.
+     * 
+     * @param val  a String to convert
+     * @return converted Integer
+     * @throws NumberFormatException if the value cannot be converted
+     */
+    public static Integer createInteger(String val) {
+        // decode() handles 0xAABD and 0777 (hex and octal) as well.
+        return Integer.decode(val);
+    }
+
+    /**
+     * Convert a String to a Long.
+     * 
+     * @param val  a String to convert
+     * @return converted Long
+     * @throws NumberFormatException if the value cannot be converted
+     */
+    public static Long createLong(String val) {
+        return Long.valueOf(val);
+    }
+
+    /**
+     * Convert a String to a BigInteger.
+     * 
+     * @param val  a String to convert
+     * @return converted BigInteger
+     * @throws NumberFormatException if the value cannot be converted
+     */
+    public static BigInteger createBigInteger(String val) {
+        BigInteger bi = new BigInteger(val);
+        return bi;
+    }
+
+    /**
+     * Convert a String to a BigDecimal.
+     * 
+     * @param val  a String to convert
+     * @return converted BigDecimal
+     * @throws NumberFormatException if the value cannot be converted
+     */
+    public static BigDecimal createBigDecimal(String val) {
+        BigDecimal bd = new BigDecimal(val);
+        return bd;
+    }
+
+    //--------------------------------------------------------------------
+    
+    /**
+     * Gets the minimum of three long values.
+     * 
+     * @param a  value 1
+     * @param b  value 2
+     * @param c  value 3
+     * @return  the smallest of the values
+     */
+    public static long minimum(long a, long b, long c) {
+        if (b < a) {
+            a = b;
+        }
+        if (c < a) {
+            a = c;
+        }
+        return a;
+    }
+
+    /**
+     * Gets the minimum of three int values.
+     * 
+     * @param a  value 1
+     * @param b  value 2
+     * @param c  value 3
+     * @return  the smallest of the values
+     */
+    public static int minimum(int a, int b, int c) {
+        if (b < a) {
+            a = b;
+        }
+        if (c < a) {
+            a = c;
+        }
+        return a;
+    }
+
+    /**
+     * Gets the maximum of three long values.
+     * 
+     * @param a  value 1
+     * @param b  value 2
+     * @param c  value 3
+     * @return  the largest of the values
+     */
+    public static long maximum(long a, long b, long c) {
+        if (b > a) {
+            a = b;
+        }
+        if (c > a) {
+            a = c;
+        }
+        return a;
+    }
+
+    /**
+     * Gets the maximum of three int values.
+     * 
+     * @param a  value 1
+     * @param b  value 2
+     * @param c  value 3
+     * @return  the largest of the values
+     */
+    public static int maximum(int a, int b, int c) {
+        if (b > a) {
+            a = b;
+        }
+        if (c > a) {
+            a = c;
+        }
+        return a;
+    }
+
+    //--------------------------------------------------------------------
+    
+    /**
+     * Compares two doubles for order.
+     *
+     * This method is more comprehensive than the standard Java greater
+     * than, less than and equals operators.
+     * 
+     *  - It returns 
-1 if the first value is less than the second.
+     *   - It returns 
+1 if the first value is greater than the second.
+     *   - It returns 
0 if the values are equal.
+     *  
+     *
+     * 
+     * The ordering is as follows, largest to smallest:
+     * 
+     *  - NaN
+     *  
 - Positive infinity
+     *  
 - Maximum double
+     *  
 - Normal positve numbers
+     *  
 - +0.0
+     *  
 - -0.0
+     *  
 - Normal negative numbers
+     *  
 - Minimum double (-Double.MAX_VALUE)
+     *  
 - Negative infinity
+     * 
 
+     * 
+     *
+     * Comparing NaN with NaN will
+     * return 0.
+     * 
+     * @param lhs  the first double
+     * @param rhs  the second double
+     * @return -1 if lhs is less, +1 if greater,
+     *  0 if equal to rhs
+     */
+    public static int compare(double lhs, double rhs) {
+        if (lhs < rhs) {
+            return -1;
+        }
+        if (lhs > rhs) {
+            return +1;
+        }
+        // Need to compare bits to handle 0.0 == -0.0 being true
+        // compare should put -0.0 < +0.0
+        // Two NaNs are also == for compare purposes
+        // where NaN == NaN is false
+        long lhsBits = Double.doubleToLongBits(lhs);
+        long rhsBits = Double.doubleToLongBits(rhs);
+        if (lhsBits == rhsBits) {
+            return 0;
+        }
+        // Something exotic! A comparison to NaN or 0.0 vs -0.0
+        // Fortunately NaN's long is > than everything else
+        // Also negzeros bits < poszero
+        // NAN: 9221120237041090560
+        // MAX: 9218868437227405311
+        // NEGZERO: -9223372036854775808
+        if (lhsBits < rhsBits) {
+            return -1;
+        } else {
+            return +1;
+        }
+    }
+    
+    /**
+     * Compares two floats for order.
+     *
+     * This method is more comprhensive than the standard Java greater than,
+     * less than and equals operators.
+     * 
+     *  - It returns 
-1 if the first value is less than the second.
+     *   - It returns 
+1 if the first value is greater than the second.
+     *   - It returns 
0 if the values are equal.
+     *  
+     *
+     *  The ordering is as follows, largest to smallest:
+     * 
+     * - NaN
+     * 
 - Positive infinity
+     * 
 - Maximum float
+     * 
 - Normal positve numbers
+     * 
 - +0.0
+     * 
 - -0.0
+     * 
 - Normal negative numbers
+     * 
 - Minimum float (-Float.MAX_VALUE)
+     * 
 - Negative infinity
+     * 
 
+     *
+     * Comparing NaN with NaN will return
+     * 0.
+     * 
+     * @param lhs  the first float
+     * @param rhs  the second float
+     * @return -1 if lhs is less, +1 if greater,
+     *  0 if equal to rhs
+     */
+    public static int compare(float lhs, float rhs) {
+        if (lhs < rhs) {
+            return -1;
+        }
+        if (lhs > rhs) {
+            return +1;
+        }
+        //Need to compare bits to handle 0.0 == -0.0 being true
+        // compare should put -0.0 < +0.0
+        // Two NaNs are also == for compare purposes
+        // where NaN == NaN is false
+        int lhsBits = Float.floatToIntBits(lhs);
+        int rhsBits = Float.floatToIntBits(rhs);
+        if (lhsBits == rhsBits) {
+            return 0;
+        }
+        //Something exotic! A comparison to NaN or 0.0 vs -0.0
+        //Fortunately NaN's int is > than everything else
+        //Also negzeros bits < poszero
+        //NAN: 2143289344
+        //MAX: 2139095039
+        //NEGZERO: -2147483648
+        if (lhsBits < rhsBits) {
+            return -1;
+        } else {
+            return +1;
+        }
+    }
+    
+    //--------------------------------------------------------------------
+    
+    /**
+     * Checks whether the String contains only
+     * digit characters.
+     *
+     * Null and empty String will return
+     * false.
+     *
+     * @param str  the String to check
+     * @return true if str contains only unicode numeric
+     */
+    public static boolean isDigits(String str) {
+        if ((str == null) || (str.length() == 0)) {
+            return false;
+        }
+        for (int i = 0; i < str.length(); i++) {
+            if (!Character.isDigit(str.charAt(i))) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Checks whether the String a valid Java number.
+     *
+     * Valid numbers include hexadecimal marked with the 0x
+     * qualifier, scientific notation and numbers marked with a type
+     * qualifier (e.g. 123L).
+     *
+     * Null and empty String will return
+     * false.
+     *
+     * @param str  the String to check
+     * @return true if the string is a correctly formatted number
+     */
+    public static boolean isNumber(String str) {
+        if ((str == null) || (str.length() == 0)) {
+            return false;
+        }
+        char[] chars = str.toCharArray();
+        int sz = chars.length;
+        boolean hasExp = false;
+        boolean hasDecPoint = false;
+        boolean allowSigns = false;
+        boolean foundDigit = false;
+        // deal with any possible sign up front
+        int start = (chars[0] == '-') ? 1 : 0;
+        if (sz > start + 1) {
+            if (chars[start] == '0' && chars[start + 1] == 'x') {
+                int i = start + 2;
+                if (i == sz) {
+                    return false; // str == "0x"
+                }
+                // checking hex (it can't be anything else)
+                for (; i < chars.length; i++) {
+                    if ((chars[i] < '0' || chars[i] > '9')
+                        && (chars[i] < 'a' || chars[i] > 'f')
+                        && (chars[i] < 'A' || chars[i] > 'F')) {
+                        return false;
+                    }
+                }
+                return true;
+            }
+        }
+        sz--; // don't want to loop to the last char, check it afterwords
+              // for type qualifiers
+        int i = start;
+        // loop to the next to last char or to the last char if we need another digit to
+        // make a valid number (e.g. chars[0..5] = "1234E")
+        while (i < sz || (i < sz + 1 && allowSigns && !foundDigit)) {
+            if (chars[i] >= '0' && chars[i] <= '9') {
+                foundDigit = true;
+                allowSigns = false;
+
+            } else if (chars[i] == '.') {
+                if (hasDecPoint || hasExp) {
+                    // two decimal points or dec in exponent   
+                    return false;
+                }
+                hasDecPoint = true;
+            } else if (chars[i] == 'e' || chars[i] == 'E') {
+                // we've already taken care of hex.
+                if (hasExp) {
+                    // two E's
+                    return false;
+                }
+                if (!foundDigit) {
+                    return false;
+                }
+                hasExp = true;
+                allowSigns = true;
+            } else if (chars[i] == '+' || chars[i] == '-') {
+                if (!allowSigns) {
+                    return false;
+                }
+                allowSigns = false;
+                foundDigit = false; // we need a digit after the E
+            } else {
+                return false;
+            }
+            i++;
+        }
+        if (i < chars.length) {
+            if (chars[i] >= '0' && chars[i] <= '9') {
+                // no type qualifier, OK
+                return true;
+            }
+            if (chars[i] == 'e' || chars[i] == 'E') {
+                // can't have an E at the last byte
+                return false;
+            }
+            if (!allowSigns
+                && (chars[i] == 'd'
+                    || chars[i] == 'D'
+                    || chars[i] == 'f'
+                    || chars[i] == 'F')) {
+                return foundDigit;
+            }
+            if (chars[i] == 'l'
+                || chars[i] == 'L') {
+                // not allowing L with an exponoent
+                return foundDigit && !hasExp;
+            }
+            // last character is illegal
+            return false;
+        }
+        // allowSigns is true iff the val ends in 'E'
+        // found digit it to make sure weird stuff like '.' and '1E-' doesn't pass
+        return !allowSigns && foundDigit;
+    }
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/ObjectUtils.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/ObjectUtils.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/ObjectUtils.java	30 Aug 2012 16:24:42 -0000	1.1
@@ -0,0 +1,293 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang;
+
+import java.io.Serializable;
+
+/**
+ * Operations on Object.
+ * 
+ * This class tries to handle null input gracefully.
+ * An exception will generally not be thrown for a null input.
+ * Each method documents its behaviour in more detail.
+ *
+ * @author Nissim Karpenstein
+ * @author Janek Bogucki
+ * @author Daniel Rall
+ * @author Stephen Colebourne
+ * @author Gary Gregory
+ * @since 1.0
+ * @version $Id: ObjectUtils.java,v 1.1 2012/08/30 16:24:42 marcin Exp $
+ */
+public class ObjectUtils {
+    
+    /**
+     * Singleton used as a null placeholder where
+     * null has another meaning.
+     *
+     * For example, in a HashMap the
+     * {@link java.util.HashMap#get(java.lang.Object)} method returns
+     * null if the Map contains
+     * null or if there is no matching key. The
+     * Null placeholder can be used to distinguish between
+     * these two cases.
+     *
+     * Another example is Hashtable, where null
+     * cannot be stored.
+     *
+     * This instance is Serializable.
+     */
+    public static final Null NULL = new Null();
+    
+    /**
+     * ObjectUtils instances should NOT be constructed in
+     * standard programming. Instead, the class should be used as
+     * ObjectUtils.defaultIfNull("a","b");.
+     *
+     * This constructor is public to permit tools that require a JavaBean instance
+     * to operate.
+     */
+    public ObjectUtils() {
+    }
+
+    // Defaulting
+    //-----------------------------------------------------------------------
+    /**
+     * Returns a default value if the object passed is
+     * null.
+     * 
+     * 
+     * ObjectUtils.defaultIfNull(null, null)      = null
+     * ObjectUtils.defaultIfNull(null, "")        = ""
+     * ObjectUtils.defaultIfNull(null, "zz")      = "zz"
+     * ObjectUtils.defaultIfNull("abc", *)        = "abc"
+     * ObjectUtils.defaultIfNull(Boolean.TRUE, *) = Boolean.TRUE
+     * 
+     *
+     * @param object  the Object to test, may be null
+     * @param defaultValue  the default value to return, may be null
+     * @return object if it is not null, defaultValue otherwise
+     */
+    public static Object defaultIfNull(Object object, Object defaultValue) {
+        return (object != null ? object : defaultValue);
+    }
+
+    /**
+     * Compares two objects for equality, where either one or both
+     * objects may be null.
+     *
+     * 
+     * ObjectUtils.equals(null, null)                  = true
+     * ObjectUtils.equals(null, "")                    = false
+     * ObjectUtils.equals("", null)                    = false
+     * ObjectUtils.equals("", "")                      = true
+     * ObjectUtils.equals(Boolean.TRUE, null)          = false
+     * ObjectUtils.equals(Boolean.TRUE, "true")        = false
+     * ObjectUtils.equals(Boolean.TRUE, Boolean.TRUE)  = true
+     * ObjectUtils.equals(Boolean.TRUE, Boolean.FALSE) = false
+     * 
+     *
+     * @param object1  the first object, may be null
+     * @param object2  the second object, may be null
+     * @return true if the values of both objects are the same
+     */
+    public static boolean equals(Object object1, Object object2) {
+        if (object1 == object2) {
+            return true;
+        }
+        if ((object1 == null) || (object2 == null)) {
+            return false;
+        }
+        return object1.equals(object2);
+    }
+    
+    // Identity ToString
+    //-----------------------------------------------------------------------
+    /**
+     * Gets the toString that would be produced by Object
+     * if a class did not override toString itself. null
+     * will return null.
+     *
+     * 
+     * ObjectUtils.identityToString(null)         = null
+     * ObjectUtils.identityToString("")           = "java.lang.String@1e23"
+     * ObjectUtils.identityToString(Boolean.TRUE) = "java.lang.Boolean@7fa"
+     * 
+     *
+     * @param object  the object to create a toString for, may be
+     *  null
+     * @return the default toString text, or null if
+     *  null passed in
+     */
+    public static String identityToString(Object object) {
+        if (object == null) {
+            return null;
+        }
+        return appendIdentityToString(null, object).toString();
+    }
+
+    /**
+     * Appends the toString that would be produced by Object
+     * if a class did not override toString itself. null
+     * will return null.
+     *
+     * 
+     * ObjectUtils.appendIdentityToString(*, null)            = null
+     * ObjectUtils.appendIdentityToString(null, "")           = "java.lang.String@1e23"
+     * ObjectUtils.appendIdentityToString(null, Boolean.TRUE) = "java.lang.Boolean@7fa"
+     * ObjectUtils.appendIdentityToString(buf, Boolean.TRUE)  = buf.append("java.lang.Boolean@7fa")
+     * 
+     *
+     * @param buffer  the buffer to append to, may be null
+     * @param object  the object to create a toString for, may be null
+     * @return the default toString text, or null if
+     *  null passed in
+     * @since 2.0
+     */
+    public static StringBuffer appendIdentityToString(StringBuffer buffer, Object object) {
+        if (object == null) {
+            return null;
+        }
+        if (buffer == null) {
+            buffer = new StringBuffer();
+        }
+        return buffer
+            .append(object.getClass().getName())
+            .append('@')
+            .append(Integer.toHexString(System.identityHashCode(object)));
+    }
+
+    // ToString
+    //-----------------------------------------------------------------------
+    /**
+     * Gets the toString of an Object returning
+     * an empty string ("") if null input.
+     * 
+     * 
+     * ObjectUtils.toString(null)         = ""
+     * ObjectUtils.toString("")           = ""
+     * ObjectUtils.toString("bat")        = "bat"
+     * ObjectUtils.toString(Boolean.TRUE) = "true"
+     * 
+     * 
+     * @see StringUtils#defaultString(String)
+     * @see String#valueOf(Object)
+     * @param obj  the Object to toString, may be null
+     * @return the passed in Object's toString, or nullStr if null input
+     * @since 2.0
+     */
+    public static String toString(Object obj) {
+        return (obj == null ? "" : obj.toString());
+    }
+
+    /**
+     * Gets the toString of an Object returning
+     * a specified text if null input.
+     * 
+     * 
+     * ObjectUtils.toString(null, null)           = null
+     * ObjectUtils.toString(null, "null")         = "null"
+     * ObjectUtils.toString("", "null")           = ""
+     * ObjectUtils.toString("bat", "null")        = "bat"
+     * ObjectUtils.toString(Boolean.TRUE, "null") = "true"
+     * 
+     * 
+     * @see StringUtils#defaultString(String,String)
+     * @see String#valueOf(Object)
+     * @param obj  the Object to toString, may be null
+     * @param nullStr  the String to return if null input, may be null
+     * @return the passed in Object's toString, or nullStr if null input
+     * @since 2.0
+     */
+    public static String toString(Object obj, String nullStr) {
+        return (obj == null ? nullStr : obj.toString());
+    }
+
+    // Null
+    //-----------------------------------------------------------------------
+    /**
+     * Class used as a null placeholder where null
+     * has another meaning.
+     *
+     * For example, in a HashMap the
+     * {@link java.util.HashMap#get(java.lang.Object)} method returns
+     * null if the Map contains
+     * null or if there is no matching key. The
+     * Null placeholder can be used to distinguish between
+     * these two cases.
+     *
+     * Another example is Hashtable, where null
+     * cannot be stored.
+     */
+    public static class Null implements Serializable {
+        // declare serialization compatability with Commons Lang 1.0
+        private static final long serialVersionUID = 7092611880189329093L;
+        
+        /**
+         * Restricted constructor - singleton.
+         */
+        Null() {
+        }
+        
+        /**
+         * Ensure singleton.
+         * 
+         * @return the singleton value
+         */
+        private Object readResolve() {
+            return ObjectUtils.NULL;
+        }
+    }
+    
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/RandomStringUtils.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/RandomStringUtils.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/RandomStringUtils.java	30 Aug 2012 16:24:42 -0000	1.1
@@ -0,0 +1,331 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang;
+
+import java.util.Random;
+/**
+ * Operations for random Strings.
+ *
+ * @author GenerationJava Core library
+ * @author Henri Yandell
+ * @author Steven Caswell
+ * @author Stephen Colebourne
+ * @author Gary Gregory
+ * @author Phil Steitz
+ * @since 1.0
+ * @version $Id: RandomStringUtils.java,v 1.1 2012/08/30 16:24:42 marcin Exp $
+ */
+public class RandomStringUtils {
+
+    /**
+     * Random object used by random method. This has to be not local
+     * to the random method so as to not return the same value in the 
+     * same millisecond.
+     */
+    private static final Random RANDOM = new Random();
+
+    /**
+     * RandomStringUtils instances should NOT be constructed in
+     * standard programming. Instead, the class should be used as
+     * RandomStringUtils.random(5);.
+     *
+     * This constructor is public to permit tools that require a JavaBean instance
+     * to operate.
+     */
+    public RandomStringUtils() {
+    }
+
+    // Random
+    //-----------------------------------------------------------------------
+    /**
+     * Creates a random string whose length is the number of characters
+     * specified.
+     *
+     * Characters will be chosen from the set of all characters.
+     *
+     * @param count  the length of random string to create
+     * @return the random string
+     */
+    public static String random(int count) {
+        return random(count, false, false);
+    }
+
+    /**
+     * Creates a random string whose length is the number of characters
+     * specified.
+     *
+     * Characters will be chosen from the set of characters whose
+     * ASCII value is between 32 and 126 (inclusive).
+     *
+     * @param count  the length of random string to create
+     * @return the random string
+     */
+    public static String randomAscii(int count) {
+        return random(count, 32, 127, false, false);
+    }
+    
+    /**
+     * Creates a random string whose length is the number of characters
+     * specified.
+     *
+     * Characters will be chosen from the set of alphabetic
+     * characters.
+     *
+     * @param count  the length of random string to create
+     * @return the random string
+     */
+    public static String randomAlphabetic(int count) {
+        return random(count, true, false);
+    }
+    
+    /**
+     * Creates a random string whose length is the number of characters
+     * specified.
+     *
+     * Characters will be chosen from the set of alpha-numeric
+     * characters.
+     *
+     * @param count  the length of random string to create
+     * @return the random string
+     */
+    public static String randomAlphanumeric(int count) {
+        return random(count, true, true);
+    }
+    
+    /**
+     * Creates a random string whose length is the number of characters
+     * specified.
+     *
+     * Characters will be chosen from the set of numeric
+     * characters.
+     *
+     * @param count  the length of random string to create
+     * @return the random string
+     */
+    public static String randomNumeric(int count) {
+        return random(count, false, true);
+    }
+
+    /**
+     * Creates a random string whose length is the number of characters
+     * specified.
+     *
+     * Characters will be chosen from the set of alpha-numeric
+     * characters as indicated by the arguments.
+     *
+     * @param count  the length of random string to create
+     * @param letters  if true, generated string will include
+     *  alphabetic characters
+     * @param numbers  if true, generatd string will include
+     *  numeric characters
+     * @return the random string
+     */
+    public static String random(int count, boolean letters, boolean numbers) {
+        return random(count, 0, 0, letters, numbers);
+    }
+    
+    /**
+     * Creates a random string whose length is the number of characters
+     * specified.
+     *
+     * Characters will be chosen from the set of alpha-numeric
+     * characters as indicated by the arguments.
+     *
+     * @param count  the length of random string to create
+     * @param start  the position in set of chars to start at
+     * @param end  the position in set of chars to end before
+     * @param letters  if true, generated string will include
+     *  alphabetic characters
+     * @param numbers  if true, generated string will include
+     *  numeric characters
+     * @return the random string
+     */
+    public static String random(int count, int start, int end, boolean letters, boolean numbers) {
+        return random(count, start, end, letters, numbers, null, RANDOM);
+    }
+
+    /**
+     * Creates a random string based on a variety of options, using
+     * default source of randomness.
+     *
+     * This method has exactly the same semantics as
+     * {@link #random(int,int,int,boolean,boolean,char[],Random)}, but
+     * instead of using an externally supplied source of randomness, it uses
+     * the internal static {@link Random} instance.
+     *
+     * @param count  the length of random string to create
+     * @param start  the position in set of chars to start at
+     * @param end  the position in set of chars to end before
+     * @param letters  only allow letters?
+     * @param numbers  only allow numbers?
+     * @param chars  the set of chars to choose randoms from.
+     *  If null, then it will use the set of all chars.
+     * @return the random string
+     * @throws ArrayIndexOutOfBoundsException if there are not
+     *  (end - start) + 1 characters in the set array.
+     */
+    public static String random(int count, int start, int end, boolean letters, boolean numbers, char[] chars) {
+        return random(count, start, end, letters, numbers, chars, RANDOM);
+    }
+
+    /**
+     * Creates a random string based on a variety of options, using
+     * supplied source of randomness.
+     *
+     * If start and end are both 0, start and end are set
+     * to ' ' and 'z', the ASCII printable
+     * characters, will be used, unless letters and numbers are both
+     * false, in which case, start and end are set to
+     * 0 and Integer.MAX_VALUE.
+     *
+     * 
If set is not null, characters between start and
+     * end are chosen.
+     *
+     * This method accepts a user-supplied {@link Random}
+     * instance to use as a source of randomness. By seeding a single 
+     * {@link Random} instance with a fixed seed and using it for each call,
+     * the same random sequence of strings can be generated repeatedly
+     * and predictably.
+     *
+     * @param count  the length of random string to create
+     * @param start  the position in set of chars to start at
+     * @param end  the position in set of chars to end before
+     * @param letters  only allow letters?
+     * @param numbers  only allow numbers?
+     * @param chars  the set of chars to choose randoms from.
+     *  If null, then it will use the set of all chars.
+     * @param random  a source of randomness.
+     * @return the random string
+     * @throws ArrayIndexOutOfBoundsException if there are not
+     *  (end - start) + 1 characters in the set array.
+     * @throws IllegalArgumentException if count < 0.
+     * @since 2.0
+     */
+    public static String random(int count, int start, int end, boolean letters, boolean numbers, char[] chars, Random random) {
+        if (count == 0) {
+            return "";
+        } else if (count < 0) {
+            throw new IllegalArgumentException("Requested random string length " + count + " is less than 0.");
+        }
+        if ((start == 0) && (end == 0)) {
+            end = 'z' + 1;
+            start = ' ';
+            if (!letters && !numbers) {
+                start = 0;
+                end = Integer.MAX_VALUE;
+            }
+        }
+
+        StringBuffer buffer = new StringBuffer();
+        int gap = end - start;
+
+        while (count-- != 0) {
+            char ch;
+            if (chars == null) {
+                ch = (char) (random.nextInt(gap) + start);
+            } else {
+                ch = chars[random.nextInt(gap) + start];
+            }
+            if ((letters && numbers && Character.isLetterOrDigit(ch))
+                || (letters && Character.isLetter(ch))
+                || (numbers && Character.isDigit(ch))
+                || (!letters && !numbers)) {
+                buffer.append(ch);
+            } else {
+                count++;
+            }
+        }
+        return buffer.toString();
+    }
+
+    /**
+     * Creates a random string whose length is the number of characters
+     * specified.
+     *
+     * Characters will be chosen from the set of characters
+     * specified.
+     *
+     * @param count  the length of random string to create
+     * @param chars  the String containing the set of characters to use,
+     *  may be null
+     * @return the random string
+     * @throws IllegalArgumentException if count < 0.
+     */
+    public static String random(int count, String chars) {
+        if (chars == null) {
+            return random(count, 0, 0, false, false, null, RANDOM);
+        }
+        return random(count, chars.toCharArray());
+    }
+
+    /**
+     * Creates a random string whose length is the number of characters
+     * specified.
+     *
+     * Characters will be chosen from the set of characters specified.
+     *
+     * @param count  the length of random string to create
+     * @param chars  the character array containing the set of characters to use,
+     *  may be null
+     * @return the random string
+     * @throws IllegalArgumentException if count < 0.
+     */
+    public static String random(int count, char[] chars) {
+        if (chars == null) {
+            return random(count, 0, 0, false, false, null, RANDOM);
+        }
+        return random(count, 0, chars.length, false, false, chars, RANDOM);
+    }
+    
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/SerializationException.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/SerializationException.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/SerializationException.java	30 Aug 2012 16:24:42 -0000	1.1
@@ -0,0 +1,110 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang;
+
+import org.apache.commons.lang.exception.NestableRuntimeException;
+
+/**
+ * Exception thrown when the Serialization process fails.
+ *
+ * The original error is wrapped within this one.
+ *
+ * @author Stephen Colebourne
+ * @since 1.0
+ * @version $Id: SerializationException.java,v 1.1 2012/08/30 16:24:42 marcin Exp $
+ */
+public class SerializationException extends NestableRuntimeException {
+
+    /**
+     * Constructs a new SerializationException without specified
+     * detail message.
+     */
+    public SerializationException() {
+        super();
+    }
+
+    /**
+     * Constructs a new SerializationException with specified
+     * detail message.
+     *
+     * @param msg  The error message.
+     */
+    public SerializationException(String msg) {
+        super(msg);
+    }
+
+    /**
+     * Constructs a new SerializationException with specified
+     * nested Throwable.
+     *
+     * @param cause  The Exception or Error
+     *  that caused this exception to be thrown.
+     */
+    public SerializationException(Throwable cause) {
+        super(cause);
+    }
+
+    /**
+     * Constructs a new SerializationException with specified
+     * detail message and nested Throwable.
+     *
+     * @param msg    The error message.
+     * @param cause  The Exception or Error
+     *  that caused this exception to be thrown.
+     */
+    public SerializationException(String msg, Throwable cause) {
+        super(msg, cause);
+    }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/SerializationUtils.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/SerializationUtils.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/SerializationUtils.java	30 Aug 2012 16:24:42 -0000	1.1
@@ -0,0 +1,232 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang;
+
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.OutputStream;
+import java.io.Serializable;
+
+/**
+ * Assists with the serialization process and performs additional functionality based 
+ * on serialization.
+ * 
+ * 
+ * - Deep clone using serialization
+ * 
 - Serialize managing finally and IOException
+ * 
 - Deserialize managing finally and IOException
+ * 
 
+ *
+ * This class throws exceptions for invalid null inputs.
+ * Each method documents its behaviour in more detail.
+ *
+ * @author Nissim Karpenstein
+ * @author Janek Bogucki
+ * @author Daniel Rall
+ * @author Stephen Colebourne
+ * @author Jeff Varszegi
+ * @author Gary Gregory
+ * @since 1.0
+ * @version $Id: SerializationUtils.java,v 1.1 2012/08/30 16:24:42 marcin Exp $
+ */
+public class SerializationUtils {
+    
+    /**
+     * SerializationUtils instances should NOT be constructed in standard programming.
+     * Instead, the class should be used as SerializationUtils.clone(object).
+     *
+     * This constructor is public to permit tools that require a JavaBean instance
+     * to operate.
+     * @since 2.0
+     */
+    public SerializationUtils() {
+        super();
+    }
+
+    // Clone
+    //-----------------------------------------------------------------------
+    /**
+     * Deep clone an Object using serialization.
+     *
+     * This is many times slower than writing clone methods by hand
+     * on all objects in your object graph. However, for complex object
+     * graphs, or for those that don't support deep cloning this can
+     * be a simple alternative implementation. Of course all the objects
+     * must be Serializable.
+     * 
+     * @param object  the Serializable object to clone
+     * @return the cloned object
+     * @throws SerializationException (runtime) if the serialization fails
+     */
+    public static Object clone(Serializable object) {
+        return deserialize(serialize(object));
+    }
+    
+    // Serialize
+    //-----------------------------------------------------------------------
+    /**
+     * Serializes an Object to the specified stream.
+     *
+     * The stream will be closed once the object is written.
+     * This avoids the need for a finally clause, and maybe also exception
+     * handling, in the application code.
+     * 
+     * The stream passed in is not buffered internally within this method.
+     * This is the responsibility of your application if desired.
+     *
+     * @param obj  the object to serialize to bytes, may be null
+     * @param outputStream  the stream to write to, must not be null
+     * @throws IllegalArgumentException if outputStream is null
+     * @throws SerializationException (runtime) if the serialization fails
+     */
+    public static void serialize(Serializable obj, OutputStream outputStream) {
+        if (outputStream == null) {
+            throw new IllegalArgumentException("The OutputStream must not be null");
+        }
+        ObjectOutputStream out = null;
+        try {
+            // stream closed in the finally
+            out = new ObjectOutputStream(outputStream);
+            out.writeObject(obj);
+            
+        } catch (IOException ex) {
+            throw new SerializationException(ex);
+        } finally {
+            try {
+                if (out != null) {
+                    out.close();
+                }
+            } catch (IOException ex) {
+                // ignore;
+            }
+        }
+    }
+
+    /**
+     * Serializes an Object to a byte array for
+     * storage/serialization.
+     *
+     * @param obj  the object to serialize to bytes
+     * @return a byte[] with the converted Serializable
+     * @throws SerializationException (runtime) if the serialization fails
+     */
+    public static byte[] serialize(Serializable obj) {
+        ByteArrayOutputStream baos = new ByteArrayOutputStream(512);
+        serialize(obj, baos);
+        return baos.toByteArray();
+    }
+
+    // Deserialize
+    //-----------------------------------------------------------------------
+    /**
+     * Deserializes an Object from the specified stream.
+     *
+     * The stream will be closed once the object is written. This
+     * avoids the need for a finally clause, and maybe also exception
+     * handling, in the application code.
+     * 
+     * The stream passed in is not buffered internally within this method.
+     * This is the responsibility of your application if desired.
+     *
+     * @param inputStream  the serialized object input stream, must not be null
+     * @return the deserialized object
+     * @throws IllegalArgumentException if inputStream is null
+     * @throws SerializationException (runtime) if the serialization fails
+     */
+    public static Object deserialize(InputStream inputStream) {
+        if (inputStream == null) {
+            throw new IllegalArgumentException("The InputStream must not be null");
+        }
+        ObjectInputStream in = null;
+        try {
+            // stream closed in the finally
+            in = new ObjectInputStream(inputStream);
+            return in.readObject();
+            
+        } catch (ClassNotFoundException ex) {
+            throw new SerializationException(ex);
+        } catch (IOException ex) {
+            throw new SerializationException(ex);
+        } finally {
+            try {
+                if (in != null) {
+                    in.close();
+                }
+            } catch (IOException ex) {
+                // ignore
+            }
+        }
+    }
+
+    /**
+     * Deserializes a single Object from an array of bytes.
+     *
+     * @param objectData  the serialized object, must not be null
+     * @return the deserialized object
+     * @throws IllegalArgumentException if objectData is null
+     * @throws SerializationException (runtime) if the serialization fails
+     */
+    public static Object deserialize(byte[] objectData) {
+        if (objectData == null) {
+            throw new IllegalArgumentException("The byte[] must not be null");
+        }
+        ByteArrayInputStream bais = new ByteArrayInputStream(objectData);
+        return deserialize(bais);
+    }
+    
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/StringEscapeUtils.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/StringEscapeUtils.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/StringEscapeUtils.java	30 Aug 2012 16:24:42 -0000	1.1
@@ -0,0 +1,552 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang;
+
+import java.io.IOException;
+import java.io.Writer;
+
+import org.apache.commons.lang.exception.NestableRuntimeException;
+
+/**
+ * Escapes and unescapes Strings for
+ * Java, Java Script, HTML, XML, and SQL.
+ *
+ * @author Apache Jakarta Turbine
+ * @author GenerationJavaCore library
+ * @author Purple Technology
+ * @author Henri Yandell
+ * @author Alexander Day Chaffee
+ * @author Antony Riley
+ * @author Helge Tesgaard
+ * @author Sean Brown
+ * @author Gary Gregory
+ * @author Phil Steitz
+ * @author Pete Gieser
+ * @since 2.0
+ * @version $Id: StringEscapeUtils.java,v 1.1 2012/08/30 16:24:42 marcin Exp $
+ */
+public class StringEscapeUtils {
+
+    /**
+     * StringEscapeUtils instances should NOT be constructed in
+     * standard programming.
+     *
+     * Instead, the class should be used as:
+     * 
StringEscapeUtils.escapeJava("foo");
+     *
+     * This constructor is public to permit tools that require a JavaBean
+     * instance to operate.
+     */
+    public StringEscapeUtils() {
+    }
+
+    // Java and JavaScript
+    //--------------------------------------------------------------------------
+    /**
+     * Escapes the characters in a String using Java String rules.
+     *
+     * Deals correctly with quotes and control-chars (tab, backslash, cr, ff, etc.) 
+     *
+     * So a tab becomes the characters '\\' and
+     * 't'.
+     *
+     * The only difference between Java strings and JavaScript strings
+     * is that in JavaScript, a single quote must be escaped.
+     *
+     * Example:
+     * 
+     * input string: He didn't say, "Stop!"
+     * output string: He didn't say, \"Stop!\"
+     * 
+     * 
+     *
+     * @param str  String to escape values in, may be null
+     * @return String with escaped values, null if null string input
+     */
+    public static String escapeJava(String str) {
+        return escapeJavaStyleString(str, false);
+    }
+
+    /**
+     * Escapes the characters in a String using Java String rules to
+     * a Writer.
+     * 
+     * A null string input has no effect.
+     * 
+     * @see #escapeJava(java.lang.String)
+     * @param out  Writer to write escaped string into
+     * @param str  String to escape values in, may be null
+     * @throws IllegalArgumentException if the Writer is null
+     * @throws IOException if error occurs on undelying Writer
+     */
+    public static void escapeJava(Writer out, String str) throws IOException {
+        escapeJavaStyleString(out, str, false);
+    }
+
+    /**
+     * Escapes the characters in a String using JavaScript String rules.
+     * Escapes any values it finds into their JavaScript String form.
+     * Deals correctly with quotes and control-chars (tab, backslash, cr, ff, etc.) 
+     *
+     * So a tab becomes the characters '\\' and
+     * 't'.
+     *
+     * The only difference between Java strings and JavaScript strings
+     * is that in JavaScript, a single quote must be escaped.
+     *
+     * Example:
+     * 
+     * input string: He didn't say, "Stop!"
+     * output string: He didn\'t say, \"Stop!\"
+     * 
+     * 
+     *
+     * @param str  String to escape values in, may be null
+     * @return String with escaped values, null if null string input
+     */
+    public static String escapeJavaScript(String str) {
+        return escapeJavaStyleString(str, true);
+    }
+
+    /**
+     * Escapes the characters in a String using JavaScript String rules
+     * to a Writer.
+     * 
+     * A null string input has no effect.
+     * 
+     * @see #escapeJavaScript(java.lang.String)
+     * @param out  Writer to write escaped string into
+     * @param str  String to escape values in, may be null
+     * @throws IllegalArgumentException if the Writer is null
+     * @throws IOException if error occurs on undelying Writer
+     **/
+    public static void escapeJavaScript(Writer out, String str) throws IOException {
+        escapeJavaStyleString(out, str, true);
+    }
+
+    private static String escapeJavaStyleString(String str, boolean escapeSingleQuotes) {
+        if (str == null) {
+            return null;
+        }
+        try {
+            StringPrintWriter writer = new StringPrintWriter(str.length() * 2);
+            escapeJavaStyleString(writer, str, escapeSingleQuotes);
+            return writer.getString();
+        } catch (IOException ioe) {
+            // this should never ever happen while writing to a StringWriter
+            ioe.printStackTrace();
+            return null;
+        }
+    }
+
+    private static void escapeJavaStyleString(Writer out, String str, boolean escapeSingleQuote) throws IOException {
+        if (out == null) {
+            throw new IllegalArgumentException("The Writer must not be null");
+        }
+        if (str == null) {
+            return;
+        }
+        int sz;
+        sz = str.length();
+        for (int i = 0; i < sz; i++) {
+            char ch = str.charAt(i);
+
+            // handle unicode
+            if (ch > 0xfff) {
+                out.write("\\u" + hex(ch));
+            } else if (ch > 0xff) {
+                out.write("\\u0" + hex(ch));
+            } else if (ch > 0x7f) {
+                out.write("\\u00" + hex(ch));
+            } else if (ch < 32) {
+                switch (ch) {
+                    case '\b':
+                        out.write('\\');
+                        out.write('b');
+                        break;
+                    case '\n':
+                        out.write('\\');
+                        out.write('n');
+                        break;
+                    case '\t':
+                        out.write('\\');
+                        out.write('t');
+                        break;
+                    case '\f':
+                        out.write('\\');
+                        out.write('f');
+                        break;
+                    case '\r':
+                        out.write('\\');
+                        out.write('r');
+                        break;
+                    default :
+                        if (ch > 0xf) {
+                            out.write("\\u00" + hex(ch));
+                        } else {
+                            out.write("\\u000" + hex(ch));
+                        }
+                        break;
+                }
+            } else {
+                switch (ch) {
+                    case '\'':
+                        if (escapeSingleQuote) out.write('\\');
+                        out.write('\'');
+                        break;
+                    case '"':
+                        out.write('\\');
+                        out.write('"');
+                        break;
+                    case '\\':
+                        out.write('\\');
+                        out.write('\\');
+                        break;
+                    default :
+                        out.write(ch);
+                        break;
+                }
+            }
+        }
+    }
+
+    /**
+     * Returns an upper case hexadecimal String for the given
+     * character.
+     * 
+     * @param ch The character to convert.
+     * @return An upper case hexadecimal String
+     */
+    private static String hex(char ch) {
+        return Integer.toHexString(ch).toUpperCase();
+    }
+
+    /**
+     * Unescapes any Java literals found in the String.
+     * For example, it will turn a sequence of '\' and
+     * 'n' into a newline character, unless the '\'
+     * is preceded by another '\'.
+     * 
+     * @param str  the String to unescape, may be null
+     * @return a new unescaped String, null if null string input
+     */
+    public static String unescapeJava(String str) {
+        if (str == null) {
+            return null;
+        }
+        try {
+            StringPrintWriter writer = new StringPrintWriter(str.length());
+            unescapeJava(writer, str);
+            return writer.getString();
+        } catch (IOException ioe) {
+            // this should never ever happen while writing to a StringWriter
+            ioe.printStackTrace();
+            return null;
+        }
+    }
+
+    /**
+     * Unescapes any Java literals found in the String to a
+     * Writer.
+     *
+     * For example, it will turn a sequence of '\' and
+     * 'n' into a newline character, unless the '\'
+     * is preceded by another '\'.
+     * 
+     * A null string input has no effect.
+     * 
+     * @param out  the Writer used to output unescaped characters
+     * @param str  the String to unescape, may be null
+     * @throws IllegalArgumentException if the Writer is null
+     * @throws IOException if error occurs on undelying Writer
+     */
+    public static void unescapeJava(Writer out, String str) throws IOException {
+        if (out == null) {
+            throw new IllegalArgumentException("The Writer must not be null");
+        }
+        if (str == null) {
+            return;
+        }
+        int sz = str.length();
+        StringBuffer unicode = new StringBuffer(4);
+        boolean hadSlash = false;
+        boolean inUnicode = false;
+        for (int i = 0; i < sz; i++) {
+            char ch = str.charAt(i);
+            if (inUnicode) {
+                // if in unicode, then we're reading unicode
+                // values in somehow
+                unicode.append(ch);
+                if (unicode.length() == 4) {
+                    // unicode now contains the four hex digits
+                    // which represents our unicode chacater
+                    try {
+                        int value = Integer.parseInt(unicode.toString(), 16);
+                        out.write((char) value);
+                        unicode.setLength(0);
+                        inUnicode = false;
+                        hadSlash = false;
+                    } catch (NumberFormatException nfe) {
+                        throw new NestableRuntimeException("Unable to parse unicode value: " + unicode, nfe);
+                    }
+                }
+                continue;
+            }
+            if (hadSlash) {
+                // handle an escaped value
+                hadSlash = false;
+                switch (ch) {
+                    case '\\':
+                        out.write('\\');
+                        break;
+                    case '\'':
+                        out.write('\'');
+                        break;
+                    case '\"':
+                        out.write('"');
+                        break;
+                    case 'r':
+                        out.write('\r');
+                        break;
+                    case 'f':
+                        out.write('\f');
+                        break;
+                    case 't':
+                        out.write('\t');
+                        break;
+                    case 'n':
+                        out.write('\n');
+                        break;
+                    case 'b':
+                        out.write('\b');
+                        break;
+                    case 'u':
+                        {
+                            // uh-oh, we're in unicode country....
+                            inUnicode = true;
+                            break;
+                        }
+                    default :
+                        out.write(ch);
+                        break;
+                }
+                continue;
+            } else if (ch == '\\') {
+                hadSlash = true;
+                continue;
+            }
+            out.write(ch);
+        }
+        if (hadSlash) {
+            // then we're in the weird case of a \ at the end of the
+            // string, let's output it anyway.
+            out.write('\\');
+        }
+    }
+
+    /**
+     * Unescapes any JavaScript literals found in the String.
+     *
+     * For example, it will turn a sequence of '\' and 'n'
+     * into a newline character, unless the '\' is preceded by another
+     * '\'.
+     *
+     * @see #unescapeJava(String)
+     * @param str  the String to unescape, may be null
+     * @return A new unescaped String, null if null string input
+     */
+    public static String unescapeJavaScript(String str) {
+        return unescapeJava(str);
+    }
+
+    /**
+     * Unescapes any JavaScript literals found in the String to a
+     * Writer.
+     *
+     * For example, it will turn a sequence of '\' and 'n'
+     * into a newline character, unless the '\' is preceded by another
+     * '\'.
+     *
+     * A null string input has no effect.
+     * 
+     * @see #unescapeJava(Writer,String)
+     * @param out  the Writer used to output unescaped characters
+     * @param str  the String to unescape, may be null
+     * @throws IllegalArgumentException if the Writer is null
+     * @throws IOException if error occurs on undelying Writer
+     */
+    public static void unescapeJavaScript(Writer out, String str) throws IOException {
+        unescapeJava(out, str);
+    }
+
+    // HTML and XML
+    //--------------------------------------------------------------------------
+    /**
+     * Escapes the characters in a String using HTML entities.
+     *
+     * 
+     * For example: "bread" & "butter" => "bread" & "butter".
+     * 
+     *
+     * Supports all known HTML 4.0 entities, including funky accents.
+     * 
+     * @param str  the String to escape, may be null
+     * @return a new escaped String, null if null string input
+     * 
+     * @see #unescapeHtml(String)
+     * @see ISO Entities
+     * @see HTML 3.2 Character Entities for ISO Latin-1
+     * @see HTML 4.0 Character entity references
+     * @see HTML 4.01 Character References
+     * @see HTML 4.01 Code positions
+     **/
+    public static String escapeHtml(String str) {
+        if (str == null) {
+            return null;
+        }
+        //todo: add a version that takes a Writer
+        //todo: rewrite underlying method to use a Writer instead of a StringBuffer
+        return Entities.HTML40.escape(str);
+    }
+
+    /**
+     * Unescapes a string containing entity escapes to a string
+     * containing the actual Unicode characters corresponding to the
+     * escapes. Supports HTML 4.0 entities.
+     *
+     * For example, the string "<Français>"
+     * will become "<Français>"
+     *
+     * If an entity is unrecognized, it is left alone, and inserted
+     * verbatim into the result string. e.g. ">&zzzz;x" will
+     * become ">&zzzz;x".
+     *
+     * @param str  the String to unescape, may be null
+     * @return a new unescaped String, null if null string input
+     * @see #escapeHtml(String)
+     **/
+    public static String unescapeHtml(String str) {
+        if (str == null) {
+            return null;
+        }
+        return Entities.HTML40.unescape(str);
+    }
+
+    /**
+     * Escapes the characters in a String using XML entities.
+     *
+     * For example: "bread" & "butter" =>
+     * "bread" & "butter".
+     * 
+     *
+     * Supports only the four basic XML entities (gt, lt, quot, amp).
+     * Does not support DTDs or external entities.
+     *
+     * @param str  the String to escape, may be null
+     * @return a new escaped String, null if null string input
+     * @see #unescapeXml(java.lang.String)
+     **/
+    public static String escapeXml(String str) {
+        if (str == null) {
+            return null;
+        }
+        return Entities.XML.escape(str);
+    }
+
+    /**
+     * Unescapes a string containing XML entity escapes to a string
+     * containing the actual Unicode characters corresponding to the
+     * escapes.
+     *
+     * Supports only the four basic XML entities (gt, lt, quot, amp).
+     * Does not support DTDs or external entities.
+     *
+     * @param str  the String to unescape, may be null
+     * @return a new unescaped String, null if null string input
+     * @see #escapeXml(String)
+     **/
+    public static String unescapeXml(String str) {
+        if (str == null) {
+            return null;
+        }
+        return Entities.XML.unescape(str);
+    }
+
+    /**
+     * Escapes the characters in a String to be suitable to pass to
+     * an SQL query.
+     *
+     * For example,
+     * 
statement.executeQuery("SELECT * FROM MOVIES WHERE TITLE='" + 
+     *   StringEscapeUtils.escapeSql("McHale's Navy") + 
+     *   "'");
+     * 
+     *
+     * At present, this method only turns single-quotes into doubled single-quotes
+     * ("McHale's Navy" => "McHale''s Navy"). It does not
+     * handle the cases of percent (%) or underscore (_) for use in LIKE clauses.
+     *
+     * see http://www.jguru.com/faq/view.jsp?EID=8881
+     * @param str  the string to escape, may be null
+     * @return a new String, escaped for SQL, null if null string input
+     */
+    public static String escapeSql(String str) {
+        if (str == null) {
+            return null;
+        }
+        return StringUtils.replace(str, "'", "''");
+    }
+
+}
+
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/StringPrintWriter.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/Attic/StringPrintWriter.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/StringPrintWriter.java	30 Aug 2012 16:24:42 -0000	1.1
@@ -0,0 +1,97 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang;
+
+import java.io.PrintWriter;
+import java.io.StringWriter;
+
+/**
+ * A PrintWriter that maintains a String as its backing store.
+ *
+ * Usage:
+ * 
+ * StringPrintWriter out = new StringPrintWriter();
+ * printTo(out);
+ * System.out.println( out.getString() );
+ * 
+ * 
+ *
+ * @author Alex Chaffee
+ * @author Scott Stanchfield
+ * @since 2.0
+ */
+class StringPrintWriter extends PrintWriter {
+    
+    public StringPrintWriter() {
+        super(new StringWriter());
+    }
+
+    public StringPrintWriter(int initialSize) {
+        super(new StringWriter(initialSize));
+    }
+
+    /**
+     * Since toString() returns information *about* this object, we
+     * want a separate method to extract just the contents of the
+     * internal buffer as a String.
+     *
+     * @return the contents of the internal string buffer
+     */
+    public String getString() {
+        flush();
+        return ((StringWriter) out).toString();
+    }
+    
+}
+
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/StringUtils.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/StringUtils.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/StringUtils.java	30 Aug 2012 16:24:42 -0000	1.1
@@ -0,0 +1,4304 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang;
+
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * Operations on {@link java.lang.String} that are 
+ * null safe.
+ * 
+ * 
+ *  - IsEmpty/IsBlank
+ *      - checks if a String contains text
 
+ *  - Trim/Strip
+ *      - removes leading and trailing whitespace
 
+ *  - Equals
+ *      - compares two strings null-safe
 
+ *  - IndexOf/LastIndexOf/Contains
+ *      - null-safe index-of checks
+ *  
 - IndexOfAny/LastIndexOfAny/IndexOfAnyBut/LastIndexOfAnyBut
+ *      - index-of any of a set of Strings
 
+ *  - ContainsOnly/ContainsNone
+ *      - does String contains only/none of these characters
 
+ *  - Substring/Left/Right/Mid
+ *      - null-safe substring extractions
 
+ *  - SubstringBefore/SubstringAfter/SubstringBetween
+ *      - substring extraction relative to other strings
 
+ *  - Split/Join
+ *      - splits a String into an array of substrings and vice versa
 
+ *  - Replace/Delete/Overlay
+ *      - Searches a String and replaces one String with another
 
+ *  - Chomp/Chop
+ *      - removes the last part of a String
 
+ *  - LeftPad/RightPad/Center/Repeat
+ *      - pads a String
 
+ *  - UpperCase/LowerCase/SwapCase/Capitalize/Uncapitalize
+ *      - changes the case of a String
 
+ *  - CountMatches
+ *      - counts the number of occurrances of one String in another
 
+ *  - IsAlpha/IsNumeric/IsWhitespace
+ *      - checks the characters in a String
 
+ *  - DefaultString
+ *      - protects against a null input String
 
+ *  - Reverse/ReverseDelimited
+ *      - reverses a String
 
+ *  - Abbreviate
+ *      - abbreviates a string using ellipsis
 
+ *  - Difference
+ *      - compares two Strings and reports on their differences
 
+ *  - LevensteinDistance
+ *      - the number of changes needed to change one String into another
 
+ * 
+ *
+ * The StringUtils class defines certain words related to
+ * String handling.
+ * 
+ * 
+ *  - null - 
null 
+ *  - empty - a zero-length string (
"") 
+ *  - space - the space character (
' ', char 32) 
+ *  - whitespace - the characters defined by {@link Character#isWhitespace(char)}
 
+ *  - trim - the characters <= 32 as in {@link String#trim()}
 
+ * 
+ * 
+ * StringUtils handles null input Strings quietly.
+ * That is to say that a null input will return null.
+ * Where a boolean or int is being returned
+ * details vary by method.
+ * 
+ * A side effect of the null handling is that a 
+ * NullPointerException should be considered a bug in
+ * StringUtils (except for deprecated methods).
+ * 
+ * Methods in this class give sample code to explain their operation.
+ * The symbol * is used to indicate any input including null.
+ *
+ * @see java.lang.String
+ * @author Apache Jakarta Turbine
+ * @author GenerationJavaCore
+ * @author Jon S. Stevens
+ * @author Daniel Rall
+ * @author Greg Coladonato
+ * @author Henri Yandell
+ * @author Ed Korthof
+ * @author Rand McNeely
+ * @author Stephen Colebourne
+ * @author Fredrik Westermarck
+ * @author Holger Krauth
+ * @author Alexander Day Chaffee
+ * @author Henning P. Schmiedehausen
+ * @author Arun Mammen Thomas
+ * @author Gary Gregory
+ * @author Phil Steitz
+ * @since 1.0
+ * @version $Id: StringUtils.java,v 1.1 2012/08/30 16:24:42 marcin Exp $
+ */
+public class StringUtils {
+    // Performance testing notes (JDK 1.4, Jul03, scolebourne)
+    // Whitespace:
+    // Character.isWhitespace() is faster than WHITESPACE.indexOf()
+    // where WHITESPACE is a string of all whitespace characters
+    // 
+    // Character access:
+    // String.charAt(n) versus toCharArray(), then array[n]
+    // String.charAt(n) is about 15% worse for a 10K string
+    // They are about equal for a length 50 string
+    // String.charAt(n) is about 4 times better for a length 3 string
+    // String.charAt(n) is best bet overall
+    //
+    // Append:
+    // String.concat about twice as fast as StringBuffer.append
+    // (not sure who tested this)
+    
+    /**
+     * The empty String "".
+     * @since 2.0
+     */
+    public static final String EMPTY = "";
+    
+    /**
+     * The maximum size to which the padding constant(s) can expand.
+     */
+    private static final int PAD_LIMIT = 8192;
+
+    /**
+     * An array of Strings used for padding.
+     *
+     * Used for efficient space padding. The length of each String expands as needed.
+     */
+    private static final String[] PADDING = new String[Character.MAX_VALUE];
+    
+    static {
+        // space padding is most common, start with 64 chars
+        PADDING[32] = "                                                                ";
+    }
+
+    /**
+     * StringUtils instances should NOT be constructed in
+     * standard programming. Instead, the class should be used as
+     * StringUtils.trim(" foo ");.
+     *
+     * This constructor is public to permit tools that require a JavaBean
+     * instance to operate.
+     */
+    public StringUtils() {
+    }
+
+    // Empty checks
+    //-----------------------------------------------------------------------
+    /**
+     * Checks if a String is empty ("") or null.
+     * 
+     * 
+     * StringUtils.isEmpty(null)      = true
+     * StringUtils.isEmpty("")        = true
+     * StringUtils.isEmpty(" ")       = false
+     * StringUtils.isEmpty("bob")     = false
+     * StringUtils.isEmpty("  bob  ") = false
+     * 
+     *
+     * NOTE: This method changed in Lang version 2.0.
+     * It no longer trims the String.
+     * That functionality is available in isBlank().
+     * 
+     * @param str  the String to check, may be null
+     * @return true if the String is empty or null
+     */
+    public static boolean isEmpty(String str) {
+        return (str == null || str.length() == 0);
+    }
+
+    /**
+     * Checks if a String is not empty ("") and not null.
+     * 
+     * 
+     * StringUtils.isNotEmpty(null)      = false
+     * StringUtils.isNotEmpty("")        = false
+     * StringUtils.isNotEmpty(" ")       = true
+     * StringUtils.isNotEmpty("bob")     = true
+     * StringUtils.isNotEmpty("  bob  ") = true
+     * 
+     *
+     * @param str  the String to check, may be null
+     * @return true if the String is not empty and not null
+     */
+    public static boolean isNotEmpty(String str) {
+        return (str != null && str.length() > 0);
+    }
+
+    /**
+     * Checks if a String is whitespace, empty ("") or null.
+     * 
+     * 
+     * StringUtils.isBlank(null)      = true
+     * StringUtils.isBlank("")        = true
+     * StringUtils.isBlank(" ")       = true
+     * StringUtils.isBlank("bob")     = false
+     * StringUtils.isBlank("  bob  ") = false
+     * 
+     *
+     * @param str  the String to check, may be null
+     * @return true if the String is null, empty or whitespace
+     * @since 2.0
+     */
+    public static boolean isBlank(String str) {
+        int strLen;
+        if (str == null || (strLen = str.length()) == 0) {
+            return true;
+        }
+        for (int i = 0; i < strLen; i++) {
+            if ((Character.isWhitespace(str.charAt(i)) == false) ) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Checks if a String is not empty (""), not null and not whitespace only.
+     * 
+     * 
+     * StringUtils.isNotBlank(null)      = false
+     * StringUtils.isNotBlank("")        = false
+     * StringUtils.isNotBlank(" ")       = false
+     * StringUtils.isNotBlank("bob")     = true
+     * StringUtils.isNotBlank("  bob  ") = true
+     * 
+     *
+     * @param str  the String to check, may be null
+     * @return true if the String is 
+     *  not empty and not null and not whitespace
+     * @since 2.0
+     */
+    public static boolean isNotBlank(String str) {
+        int strLen;
+        if (str == null || (strLen = str.length()) == 0) {
+            return false;
+        }
+        for (int i = 0; i < strLen; i++) {
+            if ((Character.isWhitespace(str.charAt(i)) == false) ) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    // Trim
+    //-----------------------------------------------------------------------
+    /**
+     * Removes control characters (char <= 32) from both
+     * ends of this String, handling null by returning
+     * an empty String ("").
+     * 
+     * 
+     * StringUtils.clean(null)          = ""
+     * StringUtils.clean("")            = ""
+     * StringUtils.clean("abc")         = "abc"
+     * StringUtils.clean("    abc    ") = "abc"
+     * StringUtils.clean("     ")       = ""
+     * 
+     *
+     * @see java.lang.String#trim()
+     * @param str  the String to clean, may be null
+     * @return the trimmed text, never null
+     * @deprecated Use the clearer named {@link #trimToEmpty(String)}.
+     *             Method will be removed in Commons Lang 3.0.
+     */
+    public static String clean(String str) {
+        return (str == null ? EMPTY : str.trim());
+    }
+
+    /**
+     * Removes control characters (char <= 32) from both
+     * ends of this String, handling null by returning
+     * null.
+     * 
+     * The String is trimmed using {@link String#trim()}.
+     * Trim removes start and end characters <= 32.
+     * To strip whitespace use {@link #strip(String)}.
+     * 
+     * To trim your choice of characters, use the
+     * {@link #strip(String, String)} methods.
+     * 
+     * 
+     * StringUtils.trim(null)          = null
+     * StringUtils.trim("")            = ""
+     * StringUtils.trim("     ")       = ""
+     * StringUtils.trim("abc")         = "abc"
+     * StringUtils.trim("    abc    ") = "abc"
+     * 
+     *
+     * @param str  the String to be trimmed, may be null
+     * @return the trimmed string, null if null String input
+     */
+    public static String trim(String str) {
+        return (str == null ? null : str.trim());
+    }
+
+    /** 
+     * Removes control characters (char <= 32) from both  
+     * ends of this String returning null if the String is 
+     * empty ("") after the trim or if it is null.
+     * 
+     * 
The String is trimmed using {@link String#trim()}.
+     * Trim removes start and end characters <= 32.
+     * To strip whitespace use {@link #stripToNull(String)}.
+     * 
+     * 
+     * StringUtils.trimToNull(null)          = null
+     * StringUtils.trimToNull("")            = null
+     * StringUtils.trimToNull("     ")       = null
+     * StringUtils.trimToNull("abc")         = "abc"
+     * StringUtils.trimToNull("    abc    ") = "abc"
+     * 
+     *  
+     * @param str  the String to be trimmed, may be null
+     * @return the trimmed String, 
+     *  null if only chars <= 32, empty or null String input
+     * @since 2.0
+     */
+    public static String trimToNull(String str) {
+        String ts = trim(str);
+        return (ts == null || ts.length() == 0 ? null : ts);
+    }
+
+    /** 
+     * Removes control characters (char <= 32) from both 
+     * ends of this String returning an empty String ("") if the String
+     * is empty ("") after the trim or if it is null.
+     * 
+     * 
The String is trimmed using {@link String#trim()}.
+     * Trim removes start and end characters <= 32.
+     * To strip whitespace use {@link #stripToEmpty(String)}.
+     * 
+     * 
+     * StringUtils.trimToEmpty(null)          = ""
+     * StringUtils.trimToEmpty("")            = ""
+     * StringUtils.trimToEmpty("     ")       = ""
+     * StringUtils.trimToEmpty("abc")         = "abc"
+     * StringUtils.trimToEmpty("    abc    ") = "abc"
+     * 
+     *  
+     * @param str  the String to be trimmed, may be null
+     * @return the trimmed String, or an empty String if null input
+     * @since 2.0
+     */
+    public static String trimToEmpty(String str) {
+        return (str == null ? EMPTY : str.trim());
+    }
+    
+    // Stripping
+    //-----------------------------------------------------------------------
+    /**
+     * Strips whitespace from the start and end of a String.
+     * 
+     * This is similar to {@link #trim(String)} but removes whitespace.
+     * Whitespace is defined by {@link Character#isWhitespace(char)}.
+     * 
+     * A null input String returns null.
+     * 
+     * 
+     * StringUtils.strip(null)     = null
+     * StringUtils.strip("")       = ""
+     * StringUtils.strip("   ")    = ""
+     * StringUtils.strip("abc")    = "abc"
+     * StringUtils.strip("  abc")  = "abc"
+     * StringUtils.strip("abc  ")  = "abc"
+     * StringUtils.strip(" abc ")  = "abc"
+     * StringUtils.strip(" ab c ") = "ab c"
+     * 
+     * 
+     * @param str  the String to remove whitespace from, may be null
+     * @return the stripped String, null if null String input
+     */
+    public static String strip(String str) {
+        return strip(str, null);
+    }
+    
+    /** 
+     * Strips whitespace from the start and end of a String  returning
+     * null if the String is empty ("") after the strip.
+     * 
+     * This is similar to {@link #trimToNull(String)} but removes whitespace.
+     * Whitespace is defined by {@link Character#isWhitespace(char)}.
+     * 
+     * 
+     * StringUtils.strip(null)     = null
+     * StringUtils.strip("")       = null
+     * StringUtils.strip("   ")    = null
+     * StringUtils.strip("abc")    = "abc"
+     * StringUtils.strip("  abc")  = "abc"
+     * StringUtils.strip("abc  ")  = "abc"
+     * StringUtils.strip(" abc ")  = "abc"
+     * StringUtils.strip(" ab c ") = "ab c"
+     * 
+     *  
+     * @param str  the String to be stripped, may be null
+     * @return the stripped String, 
+     *  null if whitespace, empty or null String input
+     * @since 2.0
+     */
+    public static String stripToNull(String str) {
+        if (str == null) {
+            return null;
+        }
+        str = strip(str, null);
+        return (str.length() == 0 ? null : str);
+    }
+
+    /** 
+     * Strips whitespace from the start and end of a String  returning
+     * an empty String if null input.
+     * 
+     * This is similar to {@link #trimToEmpty(String)} but removes whitespace.
+     * Whitespace is defined by {@link Character#isWhitespace(char)}.
+     * 
+     * 
+     * StringUtils.strip(null)     = ""
+     * StringUtils.strip("")       = ""
+     * StringUtils.strip("   ")    = ""
+     * StringUtils.strip("abc")    = "abc"
+     * StringUtils.strip("  abc")  = "abc"
+     * StringUtils.strip("abc  ")  = "abc"
+     * StringUtils.strip(" abc ")  = "abc"
+     * StringUtils.strip(" ab c ") = "ab c"
+     * 
+     *  
+     * @param str  the String to be stripped, may be null
+     * @return the trimmed String, or an empty String if null input
+     * @since 2.0
+     */
+    public static String stripToEmpty(String str) {
+        return (str == null ? EMPTY : strip(str, null));
+    }
+    
+    /**
+     * Strips any of a set of characters from the start and end of a String.
+     * This is similar to {@link String#trim()} but allows the characters
+     * to be stripped to be controlled.
+     *
+     * A null input String returns null.
+     * An empty string ("") input returns the empty string.
+     * 
+     * If the stripChars String is null, whitespace is
+     * stripped as defined by {@link Character#isWhitespace(char)}.
+     * Alternatively use {@link #strip(String)}.
+     * 
+     * 
+     * StringUtils.strip(null, *)          = null
+     * StringUtils.strip("", *)            = ""
+     * StringUtils.strip("abc", null)      = "abc"
+     * StringUtils.strip("  abc", null)    = "abc"
+     * StringUtils.strip("abc  ", null)    = "abc"
+     * StringUtils.strip(" abc ", null)    = "abc"
+     * StringUtils.strip("  abcyx", "xyz") = "  abc"
+     * 
+     * 
+     * @param str  the String to remove characters from, may be null
+     * @param stripChars  the characters to remove, null treated as whitespace
+     * @return the stripped String, null if null String input
+     */
+    public static String strip(String str, String stripChars) {
+        if (str == null || str.length() == 0) {
+            return str;
+        }
+        str = stripStart(str, stripChars);
+        return stripEnd(str, stripChars);
+    }
+
+    /**
+     * Strips any of a set of characters from the start of a String.
+     *
+     * A null input String returns null.
+     * An empty string ("") input returns the empty string.
+     * 
+     * If the stripChars String is null, whitespace is
+     * stripped as defined by {@link Character#isWhitespace(char)}.
+     * 
+     * 
+     * StringUtils.stripStart(null, *)          = null
+     * StringUtils.stripStart("", *)            = ""
+     * StringUtils.stripStart("abc", "")        = "abc"
+     * StringUtils.stripStart("abc", null)      = "abc"
+     * StringUtils.stripStart("  abc", null)    = "abc"
+     * StringUtils.stripStart("abc  ", null)    = "abc  "
+     * StringUtils.stripStart(" abc ", null)    = "abc "
+     * StringUtils.stripStart("yxabc  ", "xyz") = "abc  "
+     * 
+     * 
+     * @param str  the String to remove characters from, may be null
+     * @param stripChars  the characters to remove, null treated as whitespace
+     * @return the stripped String, null if null String input
+     */
+    public static String stripStart(String str, String stripChars) {
+        int strLen;
+        if (str == null || (strLen = str.length()) == 0) {
+            return str;
+        }
+        int start = 0;
+        if (stripChars == null) {
+            while ((start != strLen) && Character.isWhitespace(str.charAt(start))) {
+                start++;
+            }
+        } else if (stripChars.length() == 0) {
+            return str;
+        } else {
+            while ((start != strLen) && (stripChars.indexOf(str.charAt(start)) != -1)) {
+                start++;
+            }
+        }
+        return str.substring(start);
+    }
+
+    /**
+     * Strips any of a set of characters from the end of a String.
+     *
+     * A null input String returns null.
+     * An empty string ("") input returns the empty string.
+     * 
+     * If the stripChars String is null, whitespace is
+     * stripped as defined by {@link Character#isWhitespace(char)}.
+     * 
+     * 
+     * StringUtils.stripEnd(null, *)          = null
+     * StringUtils.stripEnd("", *)            = ""
+     * StringUtils.stripEnd("abc", "")        = "abc"
+     * StringUtils.stripEnd("abc", null)      = "abc"
+     * StringUtils.stripEnd("  abc", null)    = "  abc"
+     * StringUtils.stripEnd("abc  ", null)    = "abc"
+     * StringUtils.stripEnd(" abc ", null)    = " abc"
+     * StringUtils.stripEnd("  abcyx", "xyz") = "  abc"
+     * 
+     * 
+     * @param str  the String to remove characters from, may be null
+     * @param stripChars  the characters to remove, null treated as whitespace
+     * @return the stripped String, null if null String input
+     */
+    public static String stripEnd(String str, String stripChars) {
+        int end;
+        if (str == null || (end = str.length()) == 0) {
+            return str;
+        }
+ 
+        if (stripChars == null) {
+            while ((end != 0) && Character.isWhitespace(str.charAt(end - 1))) {
+                end--;
+            }
+        } else if (stripChars.length() == 0) {
+            return str;
+        } else {
+            while ((end != 0) && (stripChars.indexOf(str.charAt(end - 1)) != -1)) {
+                end--;
+            }
+        }
+        return str.substring(0, end);
+    }
+
+    // StripAll
+    //-----------------------------------------------------------------------
+    /**
+     * Strips whitespace from the start and end of every String in an array.
+     * Whitespace is defined by {@link Character#isWhitespace(char)}.
+     *
+     * A new array is returned each time, except for length zero.
+     * A null array will return null.
+     * An empty array will return itself.
+     * A null array entry will be ignored.
+     * 
+     * 
+     * StringUtils.stripAll(null)             = null
+     * StringUtils.stripAll([])               = []
+     * StringUtils.stripAll(["abc", "  abc"]) = ["abc", "abc"]
+     * StringUtils.stripAll(["abc  ", null])  = ["abc", null]
+     * 
+     * 
+     * @param strs  the array to remove whitespace from, may be null
+     * @return the stripped Strings, null if null array input
+     */
+    public static String[] stripAll(String[] strs) {
+        return stripAll(strs, null);
+    }
+ 
+    /**
+     * Strips any of a set of characters from the start and end of every
+     * String in an array.
+     * Whitespace is defined by {@link Character#isWhitespace(char)}.
+     *
+     * A new array is returned each time, except for length zero.
+     * A null array will return null.
+     * An empty array will return itself.
+     * A null array entry will be ignored.
+     * A null stripChars will strip whitespace as defined by
+     * {@link Character#isWhitespace(char)}.
+     * 
+     * 
+     * StringUtils.stripAll(null, *)                = null
+     * StringUtils.stripAll([], *)                  = []
+     * StringUtils.stripAll(["abc", "  abc"], null) = ["abc", "abc"]
+     * StringUtils.stripAll(["abc  ", null], null)  = ["abc", null]
+     * StringUtils.stripAll(["abc  ", null], "yz")  = ["abc  ", null]
+     * StringUtils.stripAll(["yabcz", null], "yz")  = ["abc", null]
+     * 
+     * 
+     * @param strs  the array to remove characters from, may be null
+     * @param stripChars  the characters to remove, null treated as whitespace
+     * @return the stripped Strings, null if null array input
+     */
+    public static String[] stripAll(String[] strs, String stripChars) {
+        int strsLen;
+        if (strs == null || (strsLen = strs.length) == 0) {
+            return strs;
+        }
+        String[] newArr = new String[strsLen];
+        for (int i = 0; i < strsLen; i++) {
+            newArr[i] = strip(strs[i], stripChars);
+        }
+        return newArr;
+    }   
+
+    // Equals
+    //-----------------------------------------------------------------------
+    /**
+     * Compares two Strings, returning true if they are equal.
+     *
+     * nulls are handled without exceptions. Two null
+     * references are considered to be equal. The comparison is case sensitive.
+     *
+     * 
+     * StringUtils.equals(null, null)   = true
+     * StringUtils.equals(null, "abc")  = false
+     * StringUtils.equals("abc", null)  = false
+     * StringUtils.equals("abc", "abc") = true
+     * StringUtils.equals("abc", "ABC") = false
+     * 
+     *  
+     * @see java.lang.String#equals(Object)
+     * @param str1  the first String, may be null
+     * @param str2  the second String, may be null
+     * @return true if the Strings are equal, case sensitive, or
+     *  both null
+     */
+    public static boolean equals(String str1, String str2) {
+        return (str1 == null ? str2 == null : str1.equals(str2));
+    }
+
+    /**
+     * Compares two Strings, returning true if they are equal ignoring
+     * the case.
+     *
+     * nulls are handled without exceptions. Two null
+     * references are considered equal. Comparison is case insensitive.
+     *
+     * 
+     * StringUtils.equalsIgnoreCase(null, null)   = true
+     * StringUtils.equalsIgnoreCase(null, "abc")  = false
+     * StringUtils.equalsIgnoreCase("abc", null)  = false
+     * StringUtils.equalsIgnoreCase("abc", "abc") = true
+     * StringUtils.equalsIgnoreCase("abc", "ABC") = true
+     * 
+     * 
+     * @see java.lang.String#equalsIgnoreCase(String)
+     * @param str1  the first String, may be null
+     * @param str2  the second String, may be null
+     * @return true if the Strings are equal, case insensitive, or
+     *  both null
+     */
+    public static boolean equalsIgnoreCase(String str1, String str2) {
+        return (str1 == null ? str2 == null : str1.equalsIgnoreCase(str2));
+    }
+
+    // IndexOf
+    //-----------------------------------------------------------------------
+    /**
+     * Finds the first index within a String, handling null.
+     * This method uses {@link String#indexOf(int)}.
+     *
+     * A null or empty ("") String will return -1.
+     * 
+     * 
+     * StringUtils.indexOf(null, *)         = -1
+     * StringUtils.indexOf("", *)           = -1
+     * StringUtils.indexOf("aabaabaa", 'a') = 0
+     * StringUtils.indexOf("aabaabaa", 'b') = 2
+     * 
+     * 
+     * @param str  the String to check, may be null
+     * @param searchChar  the character to find
+     * @return the first index of the search character, 
+     *  -1 if no match or null string input
+     * @since 2.0
+     */
+    public static int indexOf(String str, char searchChar) {
+        if (str == null || str.length() == 0) {
+            return -1;
+        }
+        return str.indexOf(searchChar);
+    }
+    
+    /**
+     * Finds the first index within a String from a start position,
+     * handling null.
+     * This method uses {@link String#indexOf(int, int)}.
+     *
+     * A null or empty ("") String will return -1.
+     * A negative start position is treated as zero.
+     * A start position greater than the string length returns -1.
+     * 
+     * 
+     * StringUtils.indexOf(null, *, *)          = -1
+     * StringUtils.indexOf("", *, *)            = -1
+     * StringUtils.indexOf("aabaabaa", 'b', 0)  = 2
+     * StringUtils.indexOf("aabaabaa", 'b', 3)  = 5
+     * StringUtils.indexOf("aabaabaa", 'b', 9)  = -1
+     * StringUtils.indexOf("aabaabaa", 'b', -1) = 2
+     * 
+     * 
+     * @param str  the String to check, may be null
+     * @param searchChar  the character to find
+     * @param startPos  the start position, negative treated as zero
+     * @return the first index of the search character, 
+     *  -1 if no match or null string input
+     * @since 2.0
+     */
+    public static int indexOf(String str, char searchChar, int startPos) {
+        if (str == null || str.length() == 0) {
+            return -1;
+        }
+        return str.indexOf(searchChar, startPos);
+    }
+    
+    /**
+     * Finds the first index within a String, handling null.
+     * This method uses {@link String#indexOf(String)}.
+     *
+     * A null String will return -1.
+     * 
+     * 
+     * StringUtils.indexOf(null, *)          = -1
+     * StringUtils.indexOf(*, null)          = -1
+     * StringUtils.indexOf("", "")           = 0
+     * StringUtils.indexOf("aabaabaa", "a")  = 0
+     * StringUtils.indexOf("aabaabaa", "b")  = 2
+     * StringUtils.indexOf("aabaabaa", "ab") = 1
+     * StringUtils.indexOf("aabaabaa", "")   = 0
+     * 
+     * 
+     * @param str  the String to check, may be null
+     * @param searchStr  the String to find, may be null
+     * @return the first index of the search String,
+     *  -1 if no match or null string input
+     * @since 2.0
+     */
+    public static int indexOf(String str, String searchStr) {
+        if (str == null || searchStr == null) {
+            return -1;
+        }
+        return str.indexOf(searchStr);
+    }
+    
+    /**
+     * Finds the first index within a String, handling null.
+     * This method uses {@link String#indexOf(String, int)}.
+     *
+     * A null String will return -1.
+     * A negative start position is treated as zero.
+     * An empty ("") search String always matches.
+     * A start position greater than the string length only matches
+     * an empty search String.
+     * 
+     * 
+     * StringUtils.indexOf(null, *, *)          = -1
+     * StringUtils.indexOf(*, null, *)          = -1
+     * StringUtils.indexOf("", "", 0)           = 0
+     * StringUtils.indexOf("aabaabaa", "a", 0)  = 0
+     * StringUtils.indexOf("aabaabaa", "b", 0)  = 2
+     * StringUtils.indexOf("aabaabaa", "ab", 0) = 1
+     * StringUtils.indexOf("aabaabaa", "b", 3)  = 5
+     * StringUtils.indexOf("aabaabaa", "b", 9)  = -1
+     * StringUtils.indexOf("aabaabaa", "b", -1) = 2
+     * StringUtils.indexOf("aabaabaa", "", 2)   = 2
+     * StringUtils.indexOf("abc", "", 9)        = 3
+     * 
+     * 
+     * @param str  the String to check, may be null
+     * @param searchStr  the String to find, may be null
+     * @param startPos  the start position, negative treated as zero
+     * @return the first index of the search String,
+     *  -1 if no match or null string input
+     * @since 2.0
+     */
+    public static int indexOf(String str, String searchStr, int startPos) {
+        if (str == null || searchStr == null) {
+            return -1;
+        }
+        // JDK1.2/JDK1.3 have a bug, when startPos > str.length for "", hence
+        if (searchStr.length() == 0 && startPos >= str.length()) {
+            return str.length();
+        }
+        return str.indexOf(searchStr, startPos);
+    }
+    
+    // LastIndexOf
+    //-----------------------------------------------------------------------
+    /**
+     * Finds the last index within a String, handling null.
+     * This method uses {@link String#lastIndexOf(int)}.
+     *
+     * A null or empty ("") String will return -1.
+     * 
+     * 
+     * StringUtils.lastIndexOf(null, *)         = -1
+     * StringUtils.lastIndexOf("", *)           = -1
+     * StringUtils.lastIndexOf("aabaabaa", 'a') = 7
+     * StringUtils.lastIndexOf("aabaabaa", 'b') = 5
+     * 
+     * 
+     * @param str  the String to check, may be null
+     * @param searchChar  the character to find
+     * @return the last index of the search character, 
+     *  -1 if no match or null string input
+     * @since 2.0
+     */
+    public static int lastIndexOf(String str, char searchChar) {
+        if (str == null || str.length() == 0) {
+            return -1;
+        }
+        return str.lastIndexOf(searchChar);
+    }
+    
+    /**
+     * Finds the last index within a String from a start position,
+     * handling null.
+     * This method uses {@link String#lastIndexOf(int, int)}.
+     *
+     * A null or empty ("") String will return -1.
+     * A negative start position returns -1.
+     * A start position greater than the string length searches the whole string.
+     * 
+     * 
+     * StringUtils.lastIndexOf(null, *, *)          = -1
+     * StringUtils.lastIndexOf("", *,  *)           = -1
+     * StringUtils.lastIndexOf("aabaabaa", 'b', 8)  = 5
+     * StringUtils.lastIndexOf("aabaabaa", 'b', 4)  = 2
+     * StringUtils.lastIndexOf("aabaabaa", 'b', 0)  = -1
+     * StringUtils.lastIndexOf("aabaabaa", 'b', 9)  = 5
+     * StringUtils.lastIndexOf("aabaabaa", 'b', -1) = -1
+     * StringUtils.lastIndexOf("aabaabaa", 'a', 0)  = 0
+     * 
+     * 
+     * @param str  the String to check, may be null
+     * @param searchChar  the character to find
+     * @param startPos  the start position
+     * @return the last index of the search character, 
+     *  -1 if no match or null string input
+     * @since 2.0
+     */
+    public static int lastIndexOf(String str, char searchChar, int startPos) {
+        if (str == null || str.length() == 0) {
+            return -1;
+        }
+        return str.lastIndexOf(searchChar, startPos);
+    }
+    
+    /**
+     * Finds the last index within a String, handling null.
+     * This method uses {@link String#lastIndexOf(String)}.
+     *
+     * A null String will return -1.
+     * 
+     * 
+     * StringUtils.lastIndexOf(null, *)          = -1
+     * StringUtils.lastIndexOf(*, null)          = -1
+     * StringUtils.lastIndexOf("", "")           = 0
+     * StringUtils.lastIndexOf("aabaabaa", "a")  = 0
+     * StringUtils.lastIndexOf("aabaabaa", "b")  = 2
+     * StringUtils.lastIndexOf("aabaabaa", "ab") = 1
+     * StringUtils.lastIndexOf("aabaabaa", "")   = 8
+     * 
+     * 
+     * @param str  the String to check, may be null
+     * @param searchStr  the String to find, may be null
+     * @return the last index of the search String,
+     *  -1 if no match or null string input
+     * @since 2.0
+     */
+    public static int lastIndexOf(String str, String searchStr) {
+        if (str == null || searchStr == null) {
+            return -1;
+        }
+        return str.lastIndexOf(searchStr);
+    }
+    
+    /**
+     * Finds the first index within a String, handling null.
+     * This method uses {@link String#lastIndexOf(String, int)}.
+     *
+     * A null String will return -1.
+     * A negative start position returns -1.
+     * An empty ("") search String always matches unless the start position is negative.
+     * A start position greater than the string length searches the whole string.
+     * 
+     * 
+     * StringUtils.lastIndexOf(null, *, *)          = -1
+     * StringUtils.lastIndexOf(*, null, *)          = -1
+     * StringUtils.lastIndexOf("aabaabaa", "a", 8)  = 7
+     * StringUtils.lastIndexOf("aabaabaa", "b", 8)  = 5
+     * StringUtils.lastIndexOf("aabaabaa", "ab", 8) = 4
+     * StringUtils.lastIndexOf("aabaabaa", "b", 9)  = 5
+     * StringUtils.lastIndexOf("aabaabaa", "b", -1) = -1
+     * StringUtils.lastIndexOf("aabaabaa", "a", 0)  = 0
+     * StringUtils.lastIndexOf("aabaabaa", "b", 0)  = -1
+     * 
+     * 
+     * @param str  the String to check, may be null
+     * @param searchStr  the String to find, may be null
+     * @param startPos  the start position, negative treated as zero
+     * @return the first index of the search String,
+     *  -1 if no match or null string input
+     * @since 2.0
+     */
+    public static int lastIndexOf(String str, String searchStr, int startPos) {
+        if (str == null || searchStr == null) {
+            return -1;
+        }
+        return str.lastIndexOf(searchStr, startPos);
+    }
+    
+    // Contains
+    //-----------------------------------------------------------------------
+    /**
+     * Checks if String contains a search character, handling null.
+     * This method uses {@link String#indexOf(int)}.
+     *
+     * A null or empty ("") String will return false.
+     * 
+     * 
+     * StringUtils.contains(null, *)    = false
+     * StringUtils.contains("", *)      = false
+     * StringUtils.contains("abc", 'a') = true
+     * StringUtils.contains("abc", 'z') = false
+     * 
+     * 
+     * @param str  the String to check, may be null
+     * @param searchChar  the character to find
+     * @return true if the String contains the search character, 
+     *  false if not or null string input
+     * @since 2.0
+     */
+    public static boolean contains(String str, char searchChar) {
+        if (str == null || str.length() == 0) {
+            return false;
+        }
+        return (str.indexOf(searchChar) >= 0);
+    }
+    
+    /**
+     * Find the first index within a String, handling null.
+     * This method uses {@link String#indexOf(int)}.
+     *
+     * A null String will return false.
+     * 
+     * 
+     * StringUtils.contains(null, *)     = false
+     * StringUtils.contains(*, null)     = false
+     * StringUtils.contains("", "")      = true
+     * StringUtils.contains("abc", "")   = true
+     * StringUtils.contains("abc", "a")  = true
+     * StringUtils.contains("abc", "z")  = false
+     * 
+     * 
+     * @param str  the String to check, may be null
+     * @param searchStr  the String to find, may be null
+     * @return true if the String contains the search character, 
+     *  false if not or null string input
+     * @since 2.0
+     */
+    public static boolean contains(String str, String searchStr) {
+        if (str == null || searchStr == null) {
+            return false;
+        }
+        return (str.indexOf(searchStr) >= 0);
+    }
+    
+    // IndexOfAny chars
+    //-----------------------------------------------------------------------
+    /**
+     * Search a String to find the first index of any
+     * character in the given set of characters.
+     *
+     * A null String will return -1.
+     * A null or zero length search array will return -1.
+     * 
+     * 
+     * StringUtils.indexOfAny(null, *)                = -1
+     * StringUtils.indexOfAny("", *)                  = -1
+     * StringUtils.indexOfAny(*, null)                = -1
+     * StringUtils.indexOfAny(*, [])                  = -1
+     * StringUtils.indexOfAny("zzabyycdxx",['z','a']) = 0
+     * StringUtils.indexOfAny("zzabyycdxx",['b','y']) = 3
+     * StringUtils.indexOfAny("aba", ['z'])           = -1
+     * 
+     * 
+     * @param str  the String to check, may be null
+     * @param searchChars  the chars to search for, may be null
+     * @return the index of any of the chars, -1 if no match or null input
+     * @since 2.0
+     */
+     public static int indexOfAny(String str, char[] searchChars) {
+         if (str == null || str.length() == 0 || searchChars == null || searchChars.length == 0) {
+             return -1;
+         }
+         for (int i = 0; i < str.length(); i ++) {
+             char ch = str.charAt(i);
+             for (int j = 0; j < searchChars.length; j++) {
+                 if (searchChars[j] == ch) {
+                     return i;
+                 }
+             }
+         }
+         return -1;
+     }
+
+    /**
+     * Search a String to find the first index of any
+     * character in the given set of characters.
+     *
+     * A null String will return -1.
+     * A null search string will return -1.
+     * 
+     * 
+     * StringUtils.indexOfAny(null, *)            = -1
+     * StringUtils.indexOfAny("", *)              = -1
+     * StringUtils.indexOfAny(*, null)            = -1
+     * StringUtils.indexOfAny(*, "")              = -1
+     * StringUtils.indexOfAny("zzabyycdxx", "za") = 0
+     * StringUtils.indexOfAny("zzabyycdxx", "by") = 3
+     * StringUtils.indexOfAny("aba","z")          = -1
+     * 
+     *  
+     * @param str  the String to check, may be null
+     * @param searchChars  the chars to search for, may be null
+     * @return the index of any of the chars, -1 if no match or null input
+     * @since 2.0
+     */
+    public static int indexOfAny(String str, String searchChars) {
+        if (str == null || str.length() == 0 || searchChars == null || searchChars.length() == 0) {
+            return -1;
+        }
+        return indexOfAny(str, searchChars.toCharArray());
+    }
+
+    // IndexOfAnyBut chars
+    //-----------------------------------------------------------------------
+    /**
+     * Search a String to find the first index of any
+     * character not in the given set of characters.
+     *
+     * A null String will return -1.
+     * A null or zero length search array will return -1.
+     * 
+     * 
+     * StringUtils.indexOfAnyBut(null, *)           = -1
+     * StringUtils.indexOfAnyBut("", *)             = -1
+     * StringUtils.indexOfAnyBut(*, null)           = -1
+     * StringUtils.indexOfAnyBut(*, [])             = -1
+     * StringUtils.indexOfAnyBut("zzabyycdxx",'za') = 3
+     * StringUtils.indexOfAnyBut("zzabyycdxx", '')  = 0
+     * StringUtils.indexOfAnyBut("aba", 'ab')       = -1
+     * 
+     * 
+     * @param str  the String to check, may be null
+     * @param searchChars  the chars to search for, may be null
+     * @return the index of any of the chars, -1 if no match or null input
+     * @since 2.0
+     */
+     public static int indexOfAnyBut(String str, char[] searchChars) {
+         if (str == null || str.length() == 0 || searchChars == null || searchChars.length == 0) {
+             return -1;
+         }
+         outer: for (int i = 0; i < str.length(); i ++) {
+             char ch = str.charAt(i);
+             for (int j = 0; j < searchChars.length; j++) {
+                 if (searchChars[j] == ch) {
+                     continue outer;
+                 }
+             }
+             return i;
+         }
+         return -1;
+     }
+
+    /**
+     * Search a String to find the first index of any
+     * character not in the given set of characters.
+     *
+     * A null String will return -1.
+     * A null search string will return -1.
+     * 
+     * 
+     * StringUtils.indexOfAnyBut(null, *)            = -1
+     * StringUtils.indexOfAnyBut("", *)              = -1
+     * StringUtils.indexOfAnyBut(*, null)            = -1
+     * StringUtils.indexOfAnyBut(*, "")              = -1
+     * StringUtils.indexOfAnyBut("zzabyycdxx", "za") = 3
+     * StringUtils.indexOfAnyBut("zzabyycdxx", "")   = 0
+     * StringUtils.indexOfAnyBut("aba","ab")         = -1
+     * 
+     *  
+     * @param str  the String to check, may be null
+     * @param searchChars  the chars to search for, may be null
+     * @return the index of any of the chars, -1 if no match or null input
+     * @since 2.0
+     */
+    public static int indexOfAnyBut(String str, String searchChars) {
+        if (str == null || str.length() == 0 || searchChars == null || searchChars.length() == 0) {
+            return -1;
+        }
+        for (int i = 0; i < str.length(); i++) {
+            if (searchChars.indexOf(str.charAt(i)) < 0) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    // ContainsOnly
+    //-----------------------------------------------------------------------
+    /**
+     * Checks if the String contains only certain characters.
+     *
+     * A null String will return false.
+     * A null valid character array will return false.
+     * An empty String ("") always returns true.
+     *
+     * 
+     * StringUtils.containsOnly(null, *)       = false
+     * StringUtils.containsOnly(*, null)       = false
+     * StringUtils.containsOnly("", *)         = true
+     * StringUtils.containsOnly("ab", '')      = false
+     * StringUtils.containsOnly("abab", 'abc') = true
+     * StringUtils.containsOnly("ab1", 'abc')  = false
+     * StringUtils.containsOnly("abz", 'abc')  = false
+     * 
+     * 
+     * @param str  the String to check, may be null
+     * @param valid  an array of valid chars, may be null
+     * @return true if it only contains valid chars and is non-null
+     */
+    public static boolean containsOnly(String str, char[] valid) {
+        // All these pre-checks are to maintain API with an older version
+        if ( (valid == null) || (str == null) ) {
+            return false;
+        }
+        if (str.length() == 0) {
+            return true;
+        }
+        if (valid.length == 0) {
+            return false;
+        }
+        return indexOfAnyBut(str, valid) == -1;
+    }
+
+    /**
+     * Checks if the String contains only certain characters.
+     *
+     * A null String will return false.
+     * A null valid character String will return false.
+     * An empty String ("") always returns true.
+     *
+     * 
+     * StringUtils.containsOnly(null, *)       = false
+     * StringUtils.containsOnly(*, null)       = false
+     * StringUtils.containsOnly("", *)         = true
+     * StringUtils.containsOnly("ab", "")      = false
+     * StringUtils.containsOnly("abab", "abc") = true
+     * StringUtils.containsOnly("ab1", "abc")  = false
+     * StringUtils.containsOnly("abz", "abc")  = false
+     * 
+     * 
+     * @param str  the String to check, may be null
+     * @param validChars  a String of valid chars, may be null
+     * @return true if it only contains valid chars and is non-null
+     * @since 2.0
+     */
+    public static boolean containsOnly(String str, String validChars) {
+        if (str == null || validChars == null) {
+            return false;
+        }
+        return containsOnly(str, validChars.toCharArray());
+    }
+    
+    // ContainsNone
+    //-----------------------------------------------------------------------
+    /**
+     * Checks that the String does not contain certain characters.
+     *
+     * A null String will return true.
+     * A null invalid character array will return true.
+     * An empty String ("") always returns true.
+     *
+     * 
+     * StringUtils.containsNone(null, *)       = true
+     * StringUtils.containsNone(*, null)       = true
+     * StringUtils.containsNone("", *)         = true
+     * StringUtils.containsNone("ab", '')      = true
+     * StringUtils.containsNone("abab", 'xyz') = true
+     * StringUtils.containsNone("ab1", 'xyz')  = true
+     * StringUtils.containsNone("abz", 'xyz')  = false
+     * 
+     * 
+     * @param str  the String to check, may be null
+     * @param invalidChars  an array of invalid chars, may be null
+     * @return true if it contains none of the invalid chars, or is null
+     * @since 2.0
+     */
+    public static boolean containsNone(String str, char[] invalidChars) {
+        if (str == null || invalidChars == null) {
+            return true;
+        }
+        int strSize = str.length();
+        int validSize = invalidChars.length;
+        for (int i = 0; i < strSize; i++) {
+            char ch = str.charAt(i);
+            for (int j = 0; j < validSize; j++) {
+                if (invalidChars[j] == ch) {
+                    return false;
+                }
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Checks that the String does not contain certain characters.
+     *
+     * A null String will return true.
+     * A null invalid character array will return true.
+     * An empty String ("") always returns true.
+     *
+     * 
+     * StringUtils.containsNone(null, *)       = true
+     * StringUtils.containsNone(*, null)       = true
+     * StringUtils.containsNone("", *)         = true
+     * StringUtils.containsNone("ab", "")      = true
+     * StringUtils.containsNone("abab", "xyz") = true
+     * StringUtils.containsNone("ab1", "xyz")  = true
+     * StringUtils.containsNone("abz", "xyz")  = false
+     * 
+     * 
+     * @param str  the String to check, may be null
+     * @param invalidChars  a String of invalid chars, may be null
+     * @return true if it contains none of the invalid chars, or is null
+     * @since 2.0
+     */
+    public static boolean containsNone(String str, String invalidChars) {
+        if (str == null || invalidChars == null) {
+            return true;
+        }
+        return containsNone(str, invalidChars.toCharArray());
+    }
+    
+    // IndexOfAny strings
+    //-----------------------------------------------------------------------
+    /**
+     * Find the first index of any of a set of potential substrings.
+     *
+     * A null String will return -1.
+     * A null or zero length search array will return -1.
+     * A null search array entry will be ignored, but a search
+     * array containing "" will return 0 if str is not
+     * null. This method uses {@link String#indexOf(String)}.
+     * 
+     * 
+     * StringUtils.indexOfAny(null, *)                     = -1
+     * StringUtils.indexOfAny(*, null)                     = -1
+     * StringUtils.indexOfAny(*, [])                       = -1
+     * StringUtils.indexOfAny("zzabyycdxx", ["ab","cd"])   = 2
+     * StringUtils.indexOfAny("zzabyycdxx", ["cd","ab"])   = 2
+     * StringUtils.indexOfAny("zzabyycdxx", ["mn","op"])   = -1
+     * StringUtils.indexOfAny("zzabyycdxx", ["zab","aby"]) = 1
+     * StringUtils.indexOfAny("zzabyycdxx", [""])          = 0
+     * StringUtils.indexOfAny("", [""])                    = 0
+     * StringUtils.indexOfAny("", ["a"])                   = -1
+     * 
+     * 
+     * @param str  the String to check, may be null
+     * @param searchStrs  the Strings to search for, may be null
+     * @return the first index of any of the searchStrs in str, -1 if no match
+     */
+    public static int indexOfAny(String str, String[] searchStrs) {
+        if ((str == null) || (searchStrs == null)) {
+            return -1;
+        }
+        int sz = searchStrs.length;
+
+        // String's can't have a MAX_VALUEth index.
+        int ret = Integer.MAX_VALUE;
+
+        int tmp = 0;
+        for (int i = 0; i < sz; i++) {
+            String search = searchStrs[i];
+            if (search == null) {
+                continue;
+            }
+            tmp = str.indexOf(search);
+            if (tmp == -1) {
+                continue;
+            }
+
+            if (tmp < ret) {
+                ret = tmp;
+            }
+        }
+
+        return (ret == Integer.MAX_VALUE) ? -1 : ret;
+    }
+
+    /**
+     * Find the latest index of any of a set of potential substrings.
+     *
+     * A null String will return -1.
+     * A null search array will return -1.
+     * A null or zero length search array entry will be ignored,
+     * but a search array containing "" will return the length of str 
+     * if str is not null. This method uses {@link String#indexOf(String)}
+     * 
+     * 
+     * StringUtils.lastIndexOfAny(null, *)                   = -1
+     * StringUtils.lastIndexOfAny(*, null)                   = -1
+     * StringUtils.lastIndexOfAny(*, [])                     = -1
+     * StringUtils.lastIndexOfAny(*, [null])                 = -1
+     * StringUtils.lastIndexOfAny("zzabyycdxx", ["ab","cd"]) = 6
+     * StringUtils.lastIndexOfAny("zzabyycdxx", ["cd","ab"]) = 6
+     * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn","op"]) = -1
+     * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn","op"]) = -1
+     * StringUtils.lastIndexOfAny("zzabyycdxx", ["mn",""])   = 10
+     * 
+     * 
+     * @param str  the String to check, may be null
+     * @param searchStrs  the Strings to search for, may be null
+     * @return the last index of any of the Strings, -1 if no match
+     */
+    public static int lastIndexOfAny(String str, String[] searchStrs) {
+        if ((str == null) || (searchStrs == null)) {
+            return -1;
+        }
+        int sz = searchStrs.length;
+        int ret = -1;
+        int tmp = 0;
+        for (int i = 0; i < sz; i++) {
+            String search = searchStrs[i];
+            if (search == null) {
+                continue;
+            }
+            tmp = str.lastIndexOf(search);
+            if (tmp > ret) {
+                ret = tmp;
+            }
+        }
+        return ret;
+    }
+
+    // Substring
+    //-----------------------------------------------------------------------
+    /**
+     * Gets a substring from the specified String avoiding exceptions.
+     *
+     * A negative start position can be used to start n
+     * characters from the end of the String.
+     *
+     * A null String will return null.
+     * An empty ("") String will return "".
+     * 
+     * 
+     * StringUtils.substring(null, *)   = null
+     * StringUtils.substring("", *)     = ""
+     * StringUtils.substring("abc", 0)  = "abc"
+     * StringUtils.substring("abc", 2)  = "c"
+     * StringUtils.substring("abc", 4)  = ""
+     * StringUtils.substring("abc", -2) = "bc"
+     * StringUtils.substring("abc", -4) = "abc"
+     * 
+     * 
+     * @param str  the String to get the substring from, may be null
+     * @param start  the position to start from, negative means
+     *  count back from the end of the String by this many characters
+     * @return substring from start position, null if null String input
+     */
+    public static String substring(String str, int start) {
+        if (str == null) {
+            return null;
+        }
+
+        // handle negatives, which means last n characters
+        if (start < 0) {
+            start = str.length() + start; // remember start is negative
+        }
+
+        if (start < 0) {
+            start = 0;
+        }
+        if (start > str.length()) {
+            return EMPTY;
+        }
+
+        return str.substring(start);
+    }
+    
+    /**
+     * Gets a substring from the specified String avoiding exceptions.
+     *
+     * A negative start position can be used to start/end n
+     * characters from the end of the String.
+     *
+     * The returned substring starts with the character in the start
+     * position and ends before the end position. All postion counting is 
+     * zero-based -- i.e., to start at the beginning of the string use 
+     * start = 0. Negative start and end positions can be used to 
+     * specify offsets relative to the end of the String.
+     *
+     * If start is not strictly to the left of end, ""
+     * is returned.
+     * 
+     * 
+     * StringUtils.substring(null, *, *)    = null
+     * StringUtils.substring("", * ,  *)    = "";
+     * StringUtils.substring("abc", 0, 2)   = "ab"
+     * StringUtils.substring("abc", 2, 0)   = ""
+     * StringUtils.substring("abc", 2, 4)   = "c"
+     * StringUtils.substring("abc", 4, 6)   = ""
+     * StringUtils.substring("abc", 2, 2)   = ""
+     * StringUtils.substring("abc", -2, -1) = "b"
+     * StringUtils.substring("abc", -4, 2)  = "ab"
+     * 
+     * 
+     * @param str  the String to get the substring from, may be null
+     * @param start  the position to start from, negative means
+     *  count back from the end of the String by this many characters
+     * @param end  the position to end at (exclusive), negative means
+     *  count back from the end of the String by this many characters
+     * @return substring from start position to end positon,
+     *  null if null String input
+     */
+    public static String substring(String str, int start, int end) {
+        if (str == null) {
+            return null;
+        }
+
+        // handle negatives
+        if (end < 0) {
+            end = str.length() + end; // remember end is negative
+        }
+        if (start < 0) {
+            start = str.length() + start; // remember start is negative
+        }
+
+        // check length next
+        if (end > str.length()) {
+            end = str.length();
+        }
+
+        // if start is greater than end, return ""
+        if (start > end) {
+            return EMPTY;
+        }
+
+        if (start < 0) {
+            start = 0;
+        }
+        if (end < 0) {
+            end = 0;
+        }
+
+        return str.substring(start, end);
+    }
+
+    // Left/Right/Mid
+    //-----------------------------------------------------------------------
+    /**
+     * Gets the leftmost len characters of a String.
+     *
+     * If len characters are not available, or the
+     * String is null, the String will be returned without
+     * an exception. An exception is thrown if len is negative.
+     *
+     * 
+     * StringUtils.left(null, *)    = null
+     * StringUtils.left(*, -ve)     = ""
+     * StringUtils.left("", *)      = ""
+     * StringUtils.left("abc", 0)   = ""
+     * StringUtils.left("abc", 2)   = "ab"
+     * StringUtils.left("abc", 4)   = "abc"
+     * 
+     * 
+     * @param str  the String to get the leftmost characters from, may be null
+     * @param len  the length of the required String, must be zero or positive
+     * @return the leftmost characters, null if null String input
+     */
+    public static String left(String str, int len) {
+        if (str == null) {
+            return null;
+        }
+        if (len < 0) {
+            return EMPTY;
+        }
+        if (str.length() <= len) {
+            return str;
+        } else {
+            return str.substring(0, len);
+        }
+    }
+
+    /**
+     * Gets the rightmost len characters of a String.
+     *
+     * If len characters are not available, or the String
+     * is null, the String will be returned without an
+     * an exception. An exception is thrown if len is negative.
+     *
+     * 
+     * StringUtils.right(null, *)    = null
+     * StringUtils.right(*, -ve)     = ""
+     * StringUtils.right("", *)      = ""
+     * StringUtils.right("abc", 0)   = ""
+     * StringUtils.right("abc", 2)   = "bc"
+     * StringUtils.right("abc", 4)   = "abc"
+     * 
+     * 
+     * @param str  the String to get the rightmost characters from, may be null
+     * @param len  the length of the required String, must be zero or positive
+     * @return the rightmost characters, null if null String input
+     */
+    public static String right(String str, int len) {
+        if (str == null) {
+            return null;
+        }
+        if (len < 0) {
+            return EMPTY;
+        }
+        if (str.length() <= len) {
+            return str;
+        } else {
+            return str.substring(str.length() - len);
+        }
+    }
+
+    /**
+     * Gets len characters from the middle of a String.
+     *
+     * If len characters are not available, the remainder
+     * of the String will be returned without an exception. If the
+     * String is null, null will be returned.
+     * An exception is thrown if len is negative.
+     *
+     * 
+     * StringUtils.mid(null, *, *)    = null
+     * StringUtils.mid(*, *, -ve)     = ""
+     * StringUtils.mid("", 0, *)      = ""
+     * StringUtils.mid("abc", 0, 2)   = "ab"
+     * StringUtils.mid("abc", 0, 4)   = "abc"
+     * StringUtils.mid("abc", 2, 4)   = "c"
+     * StringUtils.mid("abc", 4, 2)   = ""
+     * StringUtils.mid("abc", -2, 2)  = "ab"
+     * 
+     * 
+     * @param str  the String to get the characters from, may be null
+     * @param pos  the position to start from, negative treated as zero
+     * @param len  the length of the required String, must be zero or positive
+     * @return the middle characters, null if null String input
+     */
+    public static String mid(String str, int pos, int len) {
+        if (str == null) {
+            return null;
+        }
+        if (len < 0 || pos > str.length()) {
+            return EMPTY;
+        }
+        if (pos < 0) {
+            pos = 0;
+        }
+        if (str.length() <= (pos + len)) {
+            return str.substring(pos);
+        } else {
+            return str.substring(pos, pos + len);
+        }
+    }
+
+    // SubStringAfter/SubStringBefore
+    //-----------------------------------------------------------------------
+    /**
+     * Gets the substring before the first occurance of a separator.
+     * The separator is not returned.
+     *
+     * A null string input will return null.
+     * An empty ("") string input will return the empty string.
+     * A null separator will return the input string.
+     *
+     * 
+     * StringUtils.substringBefore(null, *)      = null
+     * StringUtils.substringBefore("", *)        = ""
+     * StringUtils.substringBefore("abc", "a")   = ""
+     * StringUtils.substringBefore("abcba", "b") = "a"
+     * StringUtils.substringBefore("abc", "c")   = "ab"
+     * StringUtils.substringBefore("abc", "d")   = "abc"
+     * StringUtils.substringBefore("abc", "")    = ""
+     * StringUtils.substringBefore("abc", null)  = "abc"
+     * 
+     *
+     * @param str  the String to get a substring from, may be null
+     * @param separator  the String to search for, may be null
+     * @return the substring before the first occurance of the separator,
+     *  null if null String input
+     * @since 2.0
+     */
+    public static String substringBefore(String str, String separator) {
+        if (str == null || separator == null || str.length() == 0) {
+            return str;
+        }
+        if (separator.length() == 0) {
+            return EMPTY;
+        }
+        int pos = str.indexOf(separator);
+        if (pos == -1) {
+            return str;
+        }
+        return str.substring(0, pos);
+    }
+
+    /**
+     * Gets the substring after the first occurance of a separator.
+     * The separator is not returned.
+     *
+     * A null string input will return null.
+     * An empty ("") string input will return the empty string.
+     * A null separator will return the empty string if the
+     * input string is not null.
+     * 
+     * 
+     * StringUtils.substringAfter(null, *)      = null
+     * StringUtils.substringAfter("", *)        = ""
+     * StringUtils.substringAfter(*, null)      = ""
+     * StringUtils.substringAfter("abc", "a")   = "bc"
+     * StringUtils.substringAfter("abcba", "b") = "cba"
+     * StringUtils.substringAfter("abc", "c")   = ""
+     * StringUtils.substringAfter("abc", "d")   = ""
+     * StringUtils.substringAfter("abc", "")    = "abc"
+     * 
+     *
+     * @param str  the String to get a substring from, may be null
+     * @param separator  the String to search for, may be null
+     * @return the substring after the first occurance of the separator,
+     *  null if null String input
+     * @since 2.0
+     */
+    public static String substringAfter(String str, String separator) {
+        if (str == null || str.length() == 0) {
+            return str;
+        }
+        if (separator == null) {
+            return EMPTY;
+        }
+        int pos = str.indexOf(separator);
+        if (pos == -1) {
+            return EMPTY;
+        }
+        return str.substring(pos + separator.length());
+    }
+
+    /**
+     * Gets the substring before the last occurance of a separator.
+     * The separator is not returned.
+     *
+     * A null string input will return null.
+     * An empty ("") string input will return the empty string.
+     * An empty or null separator will return the input string.
+     * 
+     * 
+     * StringUtils.substringBeforeLast(null, *)      = null
+     * StringUtils.substringBeforeLast("", *)        = ""
+     * StringUtils.substringBeforeLast("abcba", "b") = "abc"
+     * StringUtils.substringBeforeLast("abc", "c")   = "ab"
+     * StringUtils.substringBeforeLast("a", "a")     = ""
+     * StringUtils.substringBeforeLast("a", "z")     = "a"
+     * StringUtils.substringBeforeLast("a", null)    = "a"
+     * StringUtils.substringBeforeLast("a", "")      = "a"
+     * 
+     *
+     * @param str  the String to get a substring from, may be null
+     * @param separator  the String to search for, may be null
+     * @return the substring before the last occurance of the separator,
+     *  null if null String input
+     * @since 2.0
+     */
+    public static String substringBeforeLast(String str, String separator) {
+        if (str == null || separator == null || str.length() == 0 || separator.length() == 0) {
+            return str;
+        }
+        int pos = str.lastIndexOf(separator);
+        if (pos == -1) {
+            return str;
+        }
+        return str.substring(0, pos);
+    }
+
+    /**
+     * Gets the substring after the last occurance of a separator.
+     * The separator is not returned.
+     *
+     * A null string input will return null.
+     * An empty ("") string input will return the empty string.
+     * An empty or null separator will return the empty string if
+     * the input string is not null.
+     *
+     * 
+     * StringUtils.substringAfterLast(null, *)      = null
+     * StringUtils.substringAfterLast("", *)        = ""
+     * StringUtils.substringAfterLast(*, "")        = ""
+     * StringUtils.substringAfterLast(*, null)      = ""
+     * StringUtils.substringAfterLast("abc", "a")   = "bc"
+     * StringUtils.substringAfterLast("abcba", "b") = "a"
+     * StringUtils.substringAfterLast("abc", "c")   = ""
+     * StringUtils.substringAfterLast("a", "a")     = ""
+     * StringUtils.substringAfterLast("a", "z")     = ""
+     * 
+     *
+     * @param str  the String to get a substring from, may be null
+     * @param separator  the String to search for, may be null
+     * @return the substring after the last occurance of the separator,
+     *  null if null String input
+     * @since 2.0
+     */
+    public static String substringAfterLast(String str, String separator) {
+        if (str == null || str.length() == 0) {
+            return str;
+        }
+        if (separator == null || separator.length() == 0) {
+            return EMPTY;
+        }
+        int pos = str.lastIndexOf(separator);
+        if (pos == -1 || pos == (str.length() - separator.length())) {
+            return EMPTY;
+        }
+        return str.substring(pos + separator.length());
+    }
+
+    // Substring between
+    //-----------------------------------------------------------------------
+    /**
+     * Gets the String that is nested in between two instances of the
+     * same String.
+     *
+     * A null input String returns null.
+     * A null tag returns null.
+     * 
+     * 
+     * StringUtils.substringBetween(null, *)            = null
+     * StringUtils.substringBetween("", "")             = ""
+     * StringUtils.substringBetween("", "tag")          = null
+     * StringUtils.substringBetween("tagabctag", null)  = null
+     * StringUtils.substringBetween("tagabctag", "")    = ""
+     * StringUtils.substringBetween("tagabctag", "tag") = "abc"
+     * 
+     *
+     * @param str  the String containing the substring, may be null
+     * @param tag  the String before and after the substring, may be null
+     * @return the substring, null if no match
+     * @since 2.0
+     */
+    public static String substringBetween(String str, String tag) {
+        return substringBetween(str, tag, tag);
+    }
+    
+    /**
+     * Gets the String that is nested in between two Strings.
+     * Only the first match is returned.
+     * 
+     * A null input String returns null.
+     * A null open/close returns null (no match).
+     * An empty ("") open/close returns an empty string.
+     *
+     * 
+     * StringUtils.substringBetween(null, *, *)          = null
+     * StringUtils.substringBetween("", "", "")          = ""
+     * StringUtils.substringBetween("", "", "tag")       = null
+     * StringUtils.substringBetween("", "tag", "tag")    = null
+     * StringUtils.substringBetween("yabcz", null, null) = null
+     * StringUtils.substringBetween("yabcz", "", "")     = ""
+     * StringUtils.substringBetween("yabcz", "y", "z")   = "abc"
+     * StringUtils.substringBetween("yabczyabcz", "y", "z")   = "abc"
+     * 
+     *
+     * @param str  the String containing the substring, may be null
+     * @param open  the String before the substring, may be null
+     * @param close  the String after the substring, may be null
+     * @return the substring, null if no match
+     * @since 2.0
+     */
+    public static String substringBetween(String str, String open, String close) {
+        if (str == null || open == null || close == null) {
+            return null;
+        }
+        int start = str.indexOf(open);
+        if (start != -1) {
+            int end = str.indexOf(close, start + open.length());
+            if (end != -1) {
+                return str.substring(start + open.length(), end);
+            }
+        }
+        return null;
+    }
+
+    // Nested extraction
+    //-----------------------------------------------------------------------
+    /**
+     * Gets the String that is nested in between two instances of the
+     * same String.
+     *
+     * A null input String returns null.
+     * A null tag returns null.
+     * 
+     * 
+     * StringUtils.getNestedString(null, *)            = null
+     * StringUtils.getNestedString("", "")             = ""
+     * StringUtils.getNestedString("", "tag")          = null
+     * StringUtils.getNestedString("tagabctag", null)  = null
+     * StringUtils.getNestedString("tagabctag", "")    = ""
+     * StringUtils.getNestedString("tagabctag", "tag") = "abc"
+     * 
+     *
+     * @param str  the String containing nested-string, may be null
+     * @param tag  the String before and after nested-string, may be null
+     * @return the nested String, null if no match
+     * @deprecated Use the better named {@link #substringBetween(String, String)}.
+     *             Method will be removed in Commons Lang 3.0.
+     */
+    public static String getNestedString(String str, String tag) {
+        return substringBetween(str, tag, tag);
+    }
+    
+    /**
+     * Gets the String that is nested in between two Strings.
+     * Only the first match is returned.
+     * 
+     * A null input String returns null.
+     * A null open/close returns null (no match).
+     * An empty ("") open/close returns an empty string.
+     *
+     * 
+     * StringUtils.getNestedString(null, *, *)          = null
+     * StringUtils.getNestedString("", "", "")          = ""
+     * StringUtils.getNestedString("", "", "tag")       = null
+     * StringUtils.getNestedString("", "tag", "tag")    = null
+     * StringUtils.getNestedString("yabcz", null, null) = null
+     * StringUtils.getNestedString("yabcz", "", "")     = ""
+     * StringUtils.getNestedString("yabcz", "y", "z")   = "abc"
+     * StringUtils.getNestedString("yabczyabcz", "y", "z")   = "abc"
+     * 
+     *
+     * @param str  the String containing nested-string, may be null
+     * @param open  the String before nested-string, may be null
+     * @param close  the String after nested-string, may be null
+     * @return the nested String, null if no match
+     * @deprecated Use the better named {@link #substringBetween(String, String, String)}.
+     *             Method will be removed in Commons Lang 3.0.
+     */
+    public static String getNestedString(String str, String open, String close) {
+        return substringBetween(str, open, close);
+    }
+
+    // Splitting
+    //-----------------------------------------------------------------------
+    /**
+     * Splits the provided text into an array, using whitespace as the
+     * separator.
+     * Whitespace is defined by {@link Character#isWhitespace(char)}.
+     *
+     * The separator is not included in the returned String array.
+     * Adjacent separators are treated as one separator.
+     * 
+     * A null input String returns null.
+     *
+     * 
+     * StringUtils.split(null)       = null
+     * StringUtils.split("")         = []
+     * StringUtils.split("abc def")  = ["abc", "def"]
+     * StringUtils.split("abc  def") = ["abc", "def"]
+     * StringUtils.split(" abc ")    = ["abc"]
+     * 
+     * 
+     * @param str  the String to parse, may be null
+     * @return an array of parsed Strings, null if null String input
+     */
+    public static String[] split(String str) {
+        return split(str, null, -1);
+    }
+
+    /**
+     * Splits the provided text into an array, separator specified.
+     * This is an alternative to using StringTokenizer.
+     *
+     * The separator is not included in the returned String array.
+     * Adjacent separators are treated as one separator.
+     * 
+     * A null input String returns null.
+     *
+     * 
+     * StringUtils.split(null, *)         = null
+     * StringUtils.split("", *)           = []
+     * StringUtils.split("a.b.c", '.')    = ["a", "b", "c"]
+     * StringUtils.split("a..b.c", '.')   = ["a", "b", "c"]
+     * StringUtils.split("a:b:c", '.')    = ["a:b:c"]
+     * StringUtils.split("a\tb\nc", null) = ["a", "b", "c"]
+     * StringUtils.split("a b c", ' ')    = ["a", "b", "c"]
+     * 
+     * 
+     * @param str  the String to parse, may be null
+     * @param separatorChar  the character used as the delimiter,
+     *  null splits on whitespace
+     * @return an array of parsed Strings, null if null String input
+     * @since 2.0
+     */
+    public static String[] split(String str, char separatorChar) {
+        // Performance tuned for 2.0 (JDK1.4)
+        
+        if (str == null) {
+            return null;
+        }
+        int len = str.length();
+        if (len == 0) {
+            return ArrayUtils.EMPTY_STRING_ARRAY;
+        }
+        List list = new ArrayList();
+        int i =0, start = 0;
+        boolean match = false;
+        while (i < len) {
+            if (str.charAt(i) == separatorChar) {
+                if (match) {
+                    list.add(str.substring(start, i));
+                    match = false;
+                }
+                start = ++i;
+                continue;
+            }
+            match = true;
+            i++;
+        }
+        if (match) {
+            list.add(str.substring(start, i));
+        }
+        return (String[]) list.toArray(new String[list.size()]);
+    }
+
+    /**
+     * Splits the provided text into an array, separators specified.
+     * This is an alternative to using StringTokenizer.
+     *
+     * The separator is not included in the returned String array.
+     * Adjacent separators are treated as one separator.
+     * 
+     * A null input String returns null.
+     * A null separatorChars splits on whitespace.
+     *
+     * 
+     * StringUtils.split(null, *)         = null
+     * StringUtils.split("", *)           = []
+     * StringUtils.split("abc def", null) = ["abc", "def"]
+     * StringUtils.split("abc def", " ")  = ["abc", "def"]
+     * StringUtils.split("abc  def", " ") = ["abc", "def"]
+     * StringUtils.split("ab:cd:ef", ":") = ["ab", "cd", "ef"]
+     * 
+     * 
+     * @param str  the String to parse, may be null
+     * @param separatorChars  the characters used as the delimiters,
+     *  null splits on whitespace
+     * @return an array of parsed Strings, null if null String input
+     */
+    public static String[] split(String str, String separatorChars) {
+        return split(str, separatorChars, -1);
+    }
+
+    /**
+     * Splits the provided text into an array, separators specified.
+     * This is an alternative to using StringTokenizer.
+     *
+     * The separator is not included in the returned String array.
+     * Adjacent separators are treated as one separator.
+     *
+     * A null input String returns null.
+     * A null separatorChars splits on whitespace.
+     * 
+     * 
+     * StringUtils.split(null, *, *)            = null
+     * StringUtils.split("", *, *)              = []
+     * StringUtils.split("ab de fg", null, 0)   = ["ab", "cd", "ef"]
+     * StringUtils.split("ab   de fg", null, 0) = ["ab", "cd", "ef"]
+     * StringUtils.split("ab:cd:ef", ":", 0)    = ["ab", "cd", "ef"]
+     * StringUtils.split("ab:cd:ef", ":", 2)    = ["ab", "cdef"]
+     * 
+     * 
+     * @param str  the String to parse, may be null
+     * @param separatorChars  the characters used as the delimiters,
+     *  null splits on whitespace
+     * @param max  the maximum number of elements to include in the
+     *  array. A zero or negative value implies no limit
+     * @return an array of parsed Strings, null if null String input
+     */
+    public static String[] split(String str, String separatorChars, int max) {
+        // Performance tuned for 2.0 (JDK1.4)
+        // Direct code is quicker than StringTokenizer.
+        // Also, StringTokenizer uses isSpace() not isWhitespace()
+        
+        if (str == null) {
+            return null;
+        }
+        int len = str.length();
+        if (len == 0) {
+            return ArrayUtils.EMPTY_STRING_ARRAY;
+        }
+        List list = new ArrayList();
+        int sizePlus1 = 1;
+        int i =0, start = 0;
+        boolean match = false;
+        if (separatorChars == null) {
+            // Null separator means use whitespace
+            while (i < len) {
+                if (Character.isWhitespace(str.charAt(i))) {
+                    if (match) {
+                        if (sizePlus1++ == max) {
+                            i = len;
+                        }
+                        list.add(str.substring(start, i));
+                        match = false;
+                    }
+                    start = ++i;
+                    continue;
+                }
+                match = true;
+                i++;
+            }
+        } else if (separatorChars.length() == 1) {
+            // Optimise 1 character case
+            char sep = separatorChars.charAt(0);
+            while (i < len) {
+                if (str.charAt(i) == sep) {
+                    if (match) {
+                        if (sizePlus1++ == max) {
+                            i = len;
+                        }
+                        list.add(str.substring(start, i));
+                        match = false;
+                    }
+                    start = ++i;
+                    continue;
+                }
+                match = true;
+                i++;
+            }
+        } else {
+            // standard case
+            while (i < len) {
+                if (separatorChars.indexOf(str.charAt(i)) >= 0) {
+                    if (match) {
+                        if (sizePlus1++ == max) {
+                            i = len;
+                        }
+                        list.add(str.substring(start, i));
+                        match = false;
+                    }
+                    start = ++i;
+                    continue;
+                }
+                match = true;
+                i++;
+            }
+        }
+        if (match) {
+            list.add(str.substring(start, i));
+        }
+        return (String[]) list.toArray(new String[list.size()]);
+    }
+
+    // Joining
+    //-----------------------------------------------------------------------
+    /**
+     * Concatenates elements of an array into a single String.
+     * Null objects or empty strings within the array are represented by 
+     * empty strings.
+     *
+     * 
+     * StringUtils.concatenate(null)            = null
+     * StringUtils.concatenate([])              = ""
+     * StringUtils.concatenate([null])          = ""
+     * StringUtils.concatenate(["a", "b", "c"]) = "abc"
+     * StringUtils.concatenate([null, "", "a"]) = "a"
+     * 
+     * 
+     * @param array  the array of values to concatenate, may be null
+     * @return the concatenated String, null if null array input
+     * @deprecated Use the better named {@link #join(Object[])} instead.
+     *             Method will be removed in Commons Lang 3.0.
+     */
+    public static String concatenate(Object[] array) {
+        return join(array, null);
+    }
+    
+    /**
+     * Joins the elements of the provided array into a single String
+     * containing the provided list of elements.
+     *
+     * No separator is added to the joined String.
+     * Null objects or empty strings within the array are represented by 
+     * empty strings.
+     * 
+     * 
+     * StringUtils.join(null)            = null
+     * StringUtils.join([])              = ""
+     * StringUtils.join([null])          = ""
+     * StringUtils.join(["a", "b", "c"]) = "abc"
+     * StringUtils.join([null, "", "a"]) = "a"
+     * 
+     * 
+     * @param array  the array of values to join together, may be null
+     * @return the joined String, null if null array input
+     * @since 2.0
+     */
+    public static String join(Object[] array) {
+        return join(array, null);
+    }
+    
+    /**
+     * Joins the elements of the provided array into a single String
+     * containing the provided list of elements.
+     *
+     * No delimiter is added before or after the list.
+     * Null objects or empty strings within the array are represented by 
+     * empty strings.
+     *
+     * 
+     * StringUtils.join(null, *)               = null
+     * StringUtils.join([], *)                 = ""
+     * StringUtils.join([null], *)             = ""
+     * StringUtils.join(["a", "b", "c"], ';')  = "a;b;c"
+     * StringUtils.join(["a", "b", "c"], null) = "abc"
+     * StringUtils.join([null, "", "a"], ';')  = ";;a"
+     * 
+     *
+     * @param array  the array of values to join together, may be null
+     * @param separator  the separator character to use
+     * @return the joined String, null if null array input
+     * @since 2.0
+     */
+    public static String join(Object[] array, char separator) {
+        if (array == null) {
+            return null;
+        }
+        int arraySize = array.length;
+        int bufSize = (arraySize == 0 ? 0 : ((array[0] == null ? 16 : array[0].toString().length()) + 1) * arraySize);
+        StringBuffer buf = new StringBuffer(bufSize);
+
+        for (int i = 0; i < arraySize; i++) {
+            if (i > 0) {
+                buf.append(separator);
+            }
+            if (array[i] != null) {
+                buf.append(array[i]);
+            }
+        }
+        return buf.toString();
+    }
+
+    /**
+     * Joins the elements of the provided array into a single String
+     * containing the provided list of elements.
+     *
+     * No delimiter is added before or after the list.
+     * A null separator is the same as an empty String (""). 
+     * Null objects or empty strings within the array are represented by 
+     * empty strings.
+     *
+     * 
+     * StringUtils.join(null, *)                = null
+     * StringUtils.join([], *)                  = ""
+     * StringUtils.join([null], *)              = ""
+     * StringUtils.join(["a", "b", "c"], "--")  = "a--b--c"
+     * StringUtils.join(["a", "b", "c"], null)  = "abc"
+     * StringUtils.join(["a", "b", "c"], "")    = "abc"
+     * StringUtils.join([null, "", "a"], ',')   = ",,a"
+     * 
+     *
+     * @param array  the array of values to join together, may be null
+     * @param separator  the separator character to use, null treated as ""
+     * @return the joined String, null if null array input
+     */
+    public static String join(Object[] array, String separator) {
+        if (array == null) {
+            return null;
+        }
+        if (separator == null) {
+            separator = EMPTY;
+        }
+        int arraySize = array.length;
+
+        // ArraySize ==  0: Len = 0
+        // ArraySize > 0:   Len = NofStrings *(len(firstString) + len(separator))
+        //           (Assuming that all Strings are roughly equally long)
+        int bufSize 
+            = ((arraySize == 0) ? 0 
+                : arraySize * ((array[0] == null ? 16 : array[0].toString().length()) 
+                    + ((separator != null) ? separator.length(): 0)));
+
+        StringBuffer buf = new StringBuffer(bufSize);
+
+        for (int i = 0; i < arraySize; i++) {
+            if ((separator != null) && (i > 0)) {
+                buf.append(separator);
+            }
+            if (array[i] != null) {
+                buf.append(array[i]);
+            }
+        }
+        return buf.toString();
+    }
+
+    /**
+     * Joins the elements of the provided Iterator into
+     * a single String containing the provided elements.
+     *
+     * No delimiter is added before or after the list. Null objects or empty 
+     * strings within the iteration are represented by empty strings.
+     *
+     * See the examples here: {@link #join(Object[],char)}. 
+     *
+     * @param iterator  the Iterator of values to join together, may be null
+     * @param separator  the separator character to use
+     * @return the joined String, null if null iterator input
+     * @since 2.0
+     */
+    public static String join(Iterator iterator, char separator) {
+        if (iterator == null) {
+            return null;
+        }
+        StringBuffer buf = new StringBuffer(256);  // Java default is 16, probably too small
+        while (iterator.hasNext()) {
+            Object obj = iterator.next();
+            if (obj != null) {
+                buf.append(obj);
+            }
+            if (iterator.hasNext()) {
+                buf.append(separator);
+            }
+        }
+        return buf.toString();
+    }
+
+    /**
+     * Joins the elements of the provided Iterator into
+     * a single String containing the provided elements.
+     *
+     * No delimiter is added before or after the list.
+     * A null separator is the same as an empty String ("").
+     *
+     * See the examples here: {@link #join(Object[],String)}. 
+     *
+     * @param iterator  the Iterator of values to join together, may be null
+     * @param separator  the separator character to use, null treated as ""
+     * @return the joined String, null if null iterator input
+     */
+    public static String join(Iterator iterator, String separator) {
+        if (iterator == null) {
+            return null;
+        }
+        StringBuffer buf = new StringBuffer(256);  // Java default is 16, probably too small
+        while (iterator.hasNext()) {
+            Object obj = iterator.next();
+            if (obj != null) {
+                buf.append(obj);
+            }
+            if ((separator != null) && iterator.hasNext()) {
+                buf.append(separator);
+            }
+         }
+        return buf.toString();
+    }
+
+    // Delete
+    //-----------------------------------------------------------------------
+    /**
+     * Deletes all 'space' characters from a String as defined by
+     * {@link Character#isSpace(char)}.
+     * 
+     * This is the only StringUtils method that uses the 
+     * isSpace definition. You are advised to use
+     * {@link #deleteWhitespace(String)} instead as whitespace is much
+     * better localized.
+     *
+     * 
+     * StringUtils.deleteSpaces(null)           = null
+     * StringUtils.deleteSpaces("")             = ""
+     * StringUtils.deleteSpaces("abc")          = "abc"
+     * StringUtils.deleteSpaces(" \t  abc \n ") = "abc"
+     * StringUtils.deleteSpaces("ab  c")        = "abc"
+     * StringUtils.deleteSpaces("a\nb\tc     ") = "abc"
+     * 
+     *  
+     * Spaces are defined as {' ', '\t', '\r', '\n', '\b'}
+     * in line with the deprecated isSpace method.
+     *
+     * @param str  the String to delete spaces from, may be null
+     * @return the String without 'spaces', null if null String input
+     * @deprecated Use the better localized {@link #deleteWhitespace(String)}.
+     *             Method will be removed in Commons Lang 3.0.
+     */
+    public static String deleteSpaces(String str) {
+        if (str == null) {
+            return null;
+        }
+        return CharSetUtils.delete(str, " \t\r\n\b");
+    }
+
+    /**
+     * Deletes all whitespaces from a String as defined by
+     * {@link Character#isWhitespace(char)}.
+     *
+     * 
+     * StringUtils.deleteWhitespace(null)         = null
+     * StringUtils.deleteWhitespace("")           = ""
+     * StringUtils.deleteWhitespace("abc")        = "abc"
+     * StringUtils.deleteWhitespace("   ab  c  ") = "abc"
+     * 
+     *  
+     * @param str  the String to delete whitespace from, may be null
+     * @return the String without whitespaces, null if null String input
+     */
+    public static String deleteWhitespace(String str) {
+        if (str == null) {
+            return null;
+        }
+        int sz = str.length();
+        StringBuffer buffer = new StringBuffer(sz);
+        for (int i = 0; i < sz; i++) {
+            if (!Character.isWhitespace(str.charAt(i))) {
+                buffer.append(str.charAt(i));
+            }
+        }
+        return buffer.toString();
+    }
+
+    // Replacing
+    //-----------------------------------------------------------------------
+    /**
+     * Replaces a String with another String inside a larger String, once.
+     * 
+     * A null reference passed to this method is a no-op.
+     * 
+     * 
+     * StringUtils.replaceOnce(null, *, *)        = null
+     * StringUtils.replaceOnce("", *, *)          = ""
+     * StringUtils.replaceOnce("aba", null, null) = "aba"
+     * StringUtils.replaceOnce("aba", null, null) = "aba"
+     * StringUtils.replaceOnce("aba", "a", null)  = "aba"
+     * StringUtils.replaceOnce("aba", "a", "")    = "aba"
+     * StringUtils.replaceOnce("aba", "a", "z")   = "zba"
+     * 
+     * 
+     * @see #replace(String text, String repl, String with, int max)
+     * @param text  text to search and replace in, may be null
+     * @param repl  the String to search for, may be null
+     * @param with  the String to replace with, may be null
+     * @return the text with any replacements processed,
+     *  null if null String input
+     */
+    public static String replaceOnce(String text, String repl, String with) {
+        return replace(text, repl, with, 1);
+    }
+
+    /**
+     * Replaces all occurances of a String within another String.
+     *
+     * A null reference passed to this method is a no-op.
+     * 
+     * 
+     * StringUtils.replace(null, *, *)        = null
+     * StringUtils.replace("", *, *)          = ""
+     * StringUtils.replace("aba", null, null) = "aba"
+     * StringUtils.replace("aba", null, null) = "aba"
+     * StringUtils.replace("aba", "a", null)  = "aba"
+     * StringUtils.replace("aba", "a", "")    = "aba"
+     * StringUtils.replace("aba", "a", "z")   = "zbz"
+     * 
+     * 
+     * @see #replace(String text, String repl, String with, int max)
+     * @param text  text to search and replace in, may be null
+     * @param repl  the String to search for, may be null
+     * @param with  the String to replace with, may be null
+     * @return the text with any replacements processed,
+     *  null if null String input
+     */
+    public static String replace(String text, String repl, String with) {
+        return replace(text, repl, with, -1);
+    }
+
+    /**
+     * Replaces a String with another String inside a larger String,
+     * for the first max values of the search String.
+     *
+     * A null reference passed to this method is a no-op.
+     *
+     * 
+     * StringUtils.replace(null, *, *, *)         = null
+     * StringUtils.replace("", *, *, *)           = ""
+     * StringUtils.replace("abaa", null, null, 1) = "abaa"
+     * StringUtils.replace("abaa", null, null, 1) = "abaa"
+     * StringUtils.replace("abaa", "a", null, 1)  = "abaa"
+     * StringUtils.replace("abaa", "a", "", 1)    = "abaa"
+     * StringUtils.replace("abaa", "a", "z", 0)   = "abaa"
+     * StringUtils.replace("abaa", "a", "z", 1)   = "zbaa"
+     * StringUtils.replace("abaa", "a", "z", 2)   = "zbza"
+     * StringUtils.replace("abaa", "a", "z", -1)  = "zbzz"
+     * 
+     * 
+     * @param text  text to search and replace in, may be null
+     * @param repl  the String to search for, may be null
+     * @param with  the String to replace with, may be null
+     * @param max  maximum number of values to replace, or -1 if no maximum
+     * @return the text with any replacements processed,
+     *  null if null String input
+     */
+    public static String replace(String text, String repl, String with, int max) {
+        if (text == null || repl == null || with == null || repl.length() == 0 || max == 0) {
+            return text;
+        }
+
+        StringBuffer buf = new StringBuffer(text.length());
+        int start = 0, end = 0;
+        while ((end = text.indexOf(repl, start)) != -1) {
+            buf.append(text.substring(start, end)).append(with);
+            start = end + repl.length();
+
+            if (--max == 0) {
+                break;
+            }
+        }
+        buf.append(text.substring(start));
+        return buf.toString();
+    }
+    
+    // Replace, character based
+    //-----------------------------------------------------------------------
+    /**
+     * Replaces all occurrances of a character in a String with another.
+     * This is a null-safe version of {@link String#replace(char, char)}.
+     *
+     * A null string input returns null.
+     * An empty ("") string input returns an empty string.
+     * 
+     * 
+     * StringUtils.replaceChars(null, *, *)        = null
+     * StringUtils.replaceChars("", *, *)          = ""
+     * StringUtils.replaceChars("abcba", 'b', 'y') = "aycya"
+     * StringUtils.replaceChars("abcba", 'z', 'y') = "abcba"
+     * 
+     * 
+     * @param str  String to replace characters in, may be null
+     * @param searchChar  the character to search for, may be null
+     * @param replaceChar  the character to replace, may be null
+     * @return modified String, null if null string input
+     * @since 2.0
+     */
+    public static String replaceChars(String str, char searchChar, char replaceChar) {
+        if (str == null) {
+            return null;
+        }
+        return str.replace(searchChar, replaceChar);
+    }
+    
+    /**
+     * Replaces multiple characters in a String in one go.
+     * This method can also be used to delete characters.
+     *
+     * For example:
+     * replaceChars("hello", "ho", "jy") = jelly.
+     * 
+     * A null string input returns null.
+     * An empty ("") string input returns an empty string.
+     * A null or empty set of search characters returns the input string.
+     * 
+     * The length of the search characters should normally equal the length
+     * of the replace characters.
+     * If the search characters is longer, then the extra search characters
+     * are deleted.
+     * If the search characters is shorter, then the extra replace characters
+     * are ignored.
+     * 
+     * 
+     * StringUtils.replaceChars(null, *, *)           = null
+     * StringUtils.replaceChars("", *, *)             = ""
+     * StringUtils.replaceChars("abc", null, *)       = "abc"
+     * StringUtils.replaceChars("abc", "", *)         = "abc"
+     * StringUtils.replaceChars("abc", "b", null)     = "ac"
+     * StringUtils.replaceChars("abc", "b", "")       = "ac"
+     * StringUtils.replaceChars("abcba", "bc", "yz")  = "ayzya"
+     * StringUtils.replaceChars("abcba", "bc", "y")   = "ayya"
+     * StringUtils.replaceChars("abcba", "bc", "yzx") = "ayzya"
+     * 
+     * 
+     * @param str  String to replace characters in, may be null
+     * @param searchChars  a set of characters to search for, may be null
+     * @param replaceChars  a set of characters to replace, may be null
+     * @return modified String, null if null string input
+     * @since 2.0
+     */
+    public static String replaceChars(String str, String searchChars, String replaceChars) {
+        if (str == null || str.length() == 0 || searchChars == null || searchChars.length()== 0) {
+            return str;
+        }
+        char[] chars = str.toCharArray();
+        int len = chars.length;
+        boolean modified = false;
+        for (int i = 0, isize = searchChars.length(); i < isize; i++) {
+            char searchChar = searchChars.charAt(i);
+            if (replaceChars == null || i >= replaceChars.length()) {
+                // delete
+                int pos = 0;
+                for (int j = 0; j < len; j++) {
+                    if (chars[j] != searchChar) {
+                        chars[pos++] = chars[j];
+                    } else {
+                        modified = true;
+                    }
+                }
+                len = pos;
+            } else {
+                // replace
+                for (int j = 0; j < len; j++) {
+                    if (chars[j] == searchChar) {
+                        chars[j] = replaceChars.charAt(i);
+                        modified = true;
+                    }
+                }
+            }
+        }
+        if (modified == false) {
+            return str;
+        }
+        return new String(chars, 0, len);
+    }
+
+    // Overlay
+    //-----------------------------------------------------------------------
+    /**
+     * Overlays part of a String with another String.
+     *
+     * 
+     * StringUtils.overlayString(null, *, *, *)           = NullPointerException
+     * StringUtils.overlayString(*, null, *, *)           = NullPointerException
+     * StringUtils.overlayString("", "abc", 0, 0)         = "abc"
+     * StringUtils.overlayString("abcdef", null, 2, 4)    = "abef"
+     * StringUtils.overlayString("abcdef", "", 2, 4)      = "abef"
+     * StringUtils.overlayString("abcdef", "zzzz", 2, 4)  = "abzzzzef"
+     * StringUtils.overlayString("abcdef", "zzzz", 4, 2)  = "abcdzzzzcdef"
+     * StringUtils.overlayString("abcdef", "zzzz", -1, 4) = IndexOutOfBoundsException
+     * StringUtils.overlayString("abcdef", "zzzz", 2, 8)  = IndexOutOfBoundsException
+     * 
+     * 
+     * @param text  the String to do overlaying in, may be null
+     * @param overlay  the String to overlay, may be null
+     * @param start  the position to start overlaying at, must be valid
+     * @param end  the position to stop overlaying before, must be valid
+     * @return overlayed String, null if null String input
+     * @throws NullPointerException if text or overlay is null
+     * @throws IndexOutOfBoundsException if either position is invalid
+     * @deprecated Use better named {@link #overlay(String, String, int, int)} instead.
+     *             Method will be removed in Commons Lang 3.0.
+     */
+    public static String overlayString(String text, String overlay, int start, int end) {
+        return new StringBuffer(start + overlay.length() + text.length() - end + 1)
+            .append(text.substring(0, start))
+            .append(overlay)
+            .append(text.substring(end))
+            .toString();
+    }
+
+    /**
+     * Overlays part of a String with another String.
+     * 
+     * A null string input returns null.
+     * A negative index is treated as zero.
+     * An index greater than the string length is treated as the string length.
+     * The start index is always the smaller of the two indices.
+     *
+     * 
+     * StringUtils.overlay(null, *, *, *)            = null
+     * StringUtils.overlay("", "abc", 0, 0)          = "abc"
+     * StringUtils.overlay("abcdef", null, 2, 4)     = "abef"
+     * StringUtils.overlay("abcdef", "", 2, 4)       = "abef"
+     * StringUtils.overlay("abcdef", "", 4, 2)       = "abef"
+     * StringUtils.overlay("abcdef", "zzzz", 2, 4)   = "abzzzzef"
+     * StringUtils.overlay("abcdef", "zzzz", 4, 2)   = "abzzzzef"
+     * StringUtils.overlay("abcdef", "zzzz", -1, 4)  = "zzzzef"
+     * StringUtils.overlay("abcdef", "zzzz", 2, 8)   = "abzzzz"
+     * StringUtils.overlay("abcdef", "zzzz", -2, -3) = "zzzzabcdef"
+     * StringUtils.overlay("abcdef", "zzzz", 8, 10)  = "abcdefzzzz"
+     * 
+     * 
+     * @param str  the String to do overlaying in, may be null
+     * @param overlay  the String to overlay, may be null
+     * @param start  the position to start overlaying at
+     * @param end  the position to stop overlaying before
+     * @return overlayed String, null if null String input
+     * @since 2.0
+     */
+    public static String overlay(String str, String overlay, int start, int end) {
+        if (str == null) {
+            return null;
+        }
+        if (overlay == null) {
+            overlay = EMPTY;
+        }
+        int len = str.length();
+        if (start < 0) {
+            start = 0;
+        }
+        if (start > len) {
+            start = len;
+        }
+        if (end < 0) {
+            end = 0;
+        }
+        if (end > len) {
+            end = len;
+        }
+        if (start > end) {
+            int temp = start;
+            start = end;
+            end = temp;
+        }
+        return new StringBuffer(len + start - end + overlay.length() + 1)
+            .append(str.substring(0, start))
+            .append(overlay)
+            .append(str.substring(end))
+            .toString();
+    }
+
+    // Chomping
+    //-----------------------------------------------------------------------
+    /**
+     * Removes one newline from end of a String if it's there,
+     * otherwise leave it alone.  A newline is "\n",
+     * "\r", or "\r\n".
+     *
+     * NOTE: This method changed in 2.0.
+     * It now more closely matches Perl chomp.
+     *
+     * 
+     * StringUtils.chomp(null)          = null
+     * StringUtils.chomp("")            = ""
+     * StringUtils.chomp("abc \r")      = "abc "
+     * StringUtils.chomp("abc\n")       = "abc"
+     * StringUtils.chomp("abc\r\n")     = "abc"
+     * StringUtils.chomp("abc\r\n\r\n") = "abc\r\n"
+     * StringUtils.chomp("abc\n\r")     = "abc\n"
+     * StringUtils.chomp("abc\n\rabc")  = "abc\n\rabc"
+     * StringUtils.chomp("\r")          = ""
+     * StringUtils.chomp("\n")          = ""
+     * StringUtils.chomp("\r\n")        = ""
+     * 
+     *
+     * @param str  the String to chomp a newline from, may be null
+     * @return String without newline, null if null String input
+     */
+    public static String chomp(String str) {
+        if (str == null || str.length() == 0) {
+            return str;
+        }
+
+        if (str.length() == 1) {
+            char ch = str.charAt(0);
+            if (ch == '\r' || ch == '\n') {
+                return EMPTY;
+            } else {
+                return str;
+            }
+        }
+
+        int lastIdx = str.length() - 1;
+        char last = str.charAt(lastIdx);
+
+        if (last == '\n') {
+            if (str.charAt(lastIdx - 1) == '\r') {
+                lastIdx--;
+            }
+        } else if (last == '\r') {
+
+        } else {
+            lastIdx++;
+        }
+        return str.substring(0, lastIdx);
+    }
+
+    /**
+     * Removes separator from the end of
+     * str if it's there, otherwise leave it alone.
+     *
+     * NOTE: This method changed in version 2.0.
+     * It now more closely matches Perl chomp.
+     * For the previous behavior, use {@link #substringBeforeLast(String, String)}.
+     * This method uses {@link String#endsWith(String)}.
+     *
+     * 
+     * StringUtils.chomp(null, *)         = null
+     * StringUtils.chomp("", *)           = ""
+     * StringUtils.chomp("foobar", "bar") = "foo"
+     * StringUtils.chomp("foobar", "baz") = "foobar"
+     * StringUtils.chomp("foo", "foo")    = ""
+     * StringUtils.chomp("foo ", "foo")   = "foo"
+     * StringUtils.chomp(" foo", "foo")   = " "
+     * StringUtils.chomp("foo", "foooo")  = "foo"
+     * StringUtils.chomp("foo", "")       = "foo"
+     * StringUtils.chomp("foo", null)     = "foo"
+     * 
+     *
+     * @param str  the String to chomp from, may be null
+     * @param separator  separator String, may be null
+     * @return String without trailing separator, null if null String input
+     */
+    public static String chomp(String str, String separator) {
+        if (str == null || str.length() == 0 || separator == null) {
+            return str;
+        }
+        if (str.endsWith(separator)) {
+            return str.substring(0, str.length() - separator.length());
+        }
+        return str;
+    }
+
+    /**
+     * Remove any "\n" if and only if it is at the end
+     * of the supplied String.
+     * 
+     * @param str  the String to chomp from, must not be null
+     * @return String without chomped ending
+     * @throws NullPointerException if str is null
+     * @deprecated Use {@link #chomp(String)} instead.
+     *             Method will be removed in Commons Lang 3.0.
+     */
+    public static String chompLast(String str) {
+        return chompLast(str, "\n");
+    }
+    
+    /**
+     * Remove a value if and only if the String ends with that value.
+     * 
+     * @param str  the String to chomp from, must not be null
+     * @param sep  the String to chomp, must not be null
+     * @return String without chomped ending
+     * @throws NullPointerException if str or sep is null
+     * @deprecated Use {@link #chomp(String,String)} instead.
+     *             Method will be removed in Commons Lang 3.0.
+     */
+    public static String chompLast(String str, String sep) {
+        if (str.length() == 0) {
+            return str;
+        }
+        String sub = str.substring(str.length() - sep.length());
+        if (sep.equals(sub)) {
+            return str.substring(0, str.length() - sep.length());
+        } else {
+            return str;
+        }
+    }
+
+    /** 
+     * Remove everything and return the last value of a supplied String, and
+     * everything after it from a String.
+     *
+     * @param str  the String to chomp from, must not be null
+     * @param sep  the String to chomp, must not be null
+     * @return String chomped
+     * @throws NullPointerException if str or sep is null
+     * @deprecated Use {@link #substringAfterLast(String, String)} instead
+     *             (although this doesn't include the separator)
+     *             Method will be removed in Commons Lang 3.0.
+     */
+    public static String getChomp(String str, String sep) {
+        int idx = str.lastIndexOf(sep);
+        if (idx == str.length() - sep.length()) {
+            return sep;
+        } else if (idx != -1) {
+            return str.substring(idx);
+        } else {
+            return EMPTY;
+        }
+    }
+
+    /** 
+     * Remove the first value of a supplied String, and everything before it
+     * from a String.
+     *
+     * @param str  the String to chomp from, must not be null
+     * @param sep  the String to chomp, must not be null
+     * @return String without chomped beginning
+     * @throws NullPointerException if str or sep is null
+     * @deprecated Use {@link #substringAfter(String,String)} instead.
+     *             Method will be removed in Commons Lang 3.0.
+     */
+    public static String prechomp(String str, String sep) {
+        int idx = str.indexOf(sep);
+        if (idx != -1) {
+            return str.substring(idx + sep.length());
+        } else {
+            return str;
+        }
+    }
+
+    /** 
+     * Remove and return everything before the first value of a
+     * supplied String from another String.
+     *
+     * @param str  the String to chomp from, must not be null
+     * @param sep  the String to chomp, must not be null
+     * @return String prechomped
+     * @throws NullPointerException if str or sep is null
+     * @deprecated Use {@link #substringBefore(String,String)} instead
+     *             (although this doesn't include the separator).
+     *             Method will be removed in Commons Lang 3.0.
+     */
+    public static String getPrechomp(String str, String sep) {
+        int idx = str.indexOf(sep);
+        if (idx != -1) {
+            return str.substring(0, idx + sep.length());
+        } else {
+            return EMPTY;
+        }
+    }
+
+    // Chopping
+    //-----------------------------------------------------------------------
+    /**
+     * Remove the last character from a String.
+     *
+     * If the String ends in \r\n, then remove both
+     * of them.
+     *
+     * 
+     * StringUtils.chop(null)          = null
+     * StringUtils.chop("")            = ""
+     * StringUtils.chop("abc \r")      = "abc "
+     * StringUtils.chop("abc\n")       = "abc"
+     * StringUtils.chop("abc\r\n")     = "abc"
+     * StringUtils.chop("abc")         = "ab"
+     * StringUtils.chop("abc\nabc")    = "abc\nab"
+     * StringUtils.chop("a")           = ""
+     * StringUtils.chop("\r")          = ""
+     * StringUtils.chop("\n")          = ""
+     * StringUtils.chop("\r\n")        = ""
+     * 
+     *
+     * @param str  the String to chop last character from, may be null
+     * @return String without last character, null if null String input
+     */
+    public static String chop(String str) {
+        if (str == null) {
+            return null;
+        }
+        int strLen = str.length();
+        if (strLen < 2) {
+            return EMPTY;
+        }
+        int lastIdx = strLen - 1;
+        String ret = str.substring(0, lastIdx);
+        char last = str.charAt(lastIdx);
+        if (last == '\n') {
+            if (ret.charAt(lastIdx - 1) == '\r') {
+                return ret.substring(0, lastIdx - 1);
+            }
+        }
+        return ret;
+    }
+
+    /**
+     * Removes \n from end of a String if it's there.
+     * If a \r precedes it, then remove that too.
+     *
+     * @param str  the String to chop a newline from, must not be null
+     * @return String without newline
+     * @throws NullPointerException if str is null
+     * @deprecated Use {@link #chomp(String)} instead.
+     *             Method will be removed in Commons Lang 3.0.
+     */
+    public static String chopNewline(String str) {
+        int lastIdx = str.length() - 1;
+        if (lastIdx <= 0) {
+            return EMPTY;
+        }
+        char last = str.charAt(lastIdx);
+        if (last == '\n') {
+            if (str.charAt(lastIdx - 1) == '\r') {
+                lastIdx--;
+            }
+        } else {
+            lastIdx++;
+        }
+        return str.substring(0, lastIdx);
+    }
+
+
+    // Conversion
+    //-----------------------------------------------------------------------
+    /**
+     * Escapes any values it finds into their String form.
+     *
+     * So a tab becomes the characters '\\' and
+     * 't'.
+     *
+     * As of Lang 2.0, this calls {@link StringEscapeUtils#escapeJava(String)}
+     * behind the scenes.
+     * 
+     * @see StringEscapeUtils#escapeJava(java.lang.String)
+     * @param str String to escape values in
+     * @return String with escaped values
+     * @throws NullPointerException if str is null
+     * @deprecated Use {@link StringEscapeUtils#escapeJava(String)}
+     *             This method will be removed in Commons Lang 3.0
+     */
+    public static String escape(String str) {
+        return StringEscapeUtils.escapeJava(str);
+    }
+
+    // Padding
+    //-----------------------------------------------------------------------
+    /**
+     * Repeat a String repeat times to form a
+     * new String.
+     *
+     * 
+     * StringUtils.repeat(null, 2) = null
+     * StringUtils.repeat("", 0)   = ""
+     * StringUtils.repeat("", 2)   = ""
+     * StringUtils.repeat("a", 3)  = "aaa"
+     * StringUtils.repeat("ab", 2) = "abab"
+     * StringUtils.repeat("a", -2) = ""
+     * 
+     *
+     * @param str  the String to repeat, may be null
+     * @param repeat  number of times to repeat str, negative treated as zero
+     * @return a new String consisting of the original String repeated,
+     *  null if null String input
+     */
+    public static String repeat(String str, int repeat) {
+        // Performance tuned for 2.0 (JDK1.4)
+        
+        if (str == null) {
+            return null;
+        }
+        if (repeat <= 0) {
+            return EMPTY;
+        }
+        int inputLength = str.length();
+        if (repeat == 1 || inputLength == 0) {
+            return str;
+        }
+        if (inputLength == 1 && repeat <= PAD_LIMIT) {
+           return padding(repeat, str.charAt(0));
+        }
+
+        int outputLength = inputLength * repeat;
+        switch (inputLength) {
+            case 1:
+                char ch = str.charAt(0);
+                char[] output1 = new char[outputLength];
+                for (int i = repeat - 1; i >= 0; i--) {
+                    output1[i] = ch;
+                }
+                return new String(output1);
+            case 2:
+                char ch0 = str.charAt(0);
+                char ch1 = str.charAt(1);
+                char[] output2 = new char[outputLength];
+                for (int i = repeat * 2 - 2; i >= 0; i--,i--) {
+                    output2[i] = ch0;
+                    output2[i + 1] = ch1;
+                }
+                return new String(output2);
+            default:
+                StringBuffer buf = new StringBuffer(outputLength);
+                for (int i = 0; i < repeat; i++) {
+                    buf.append(str);
+                }        
+                return buf.toString();
+        }
+    }
+
+    /**
+     * Returns padding using the specified delimiter repeated
+     * to a given length.
+     *
+     * 
+     * StringUtils.padding(0, 'e')  = ""
+     * StringUtils.padding(3, 'e')  = "eee"
+     * StringUtils.padding(-2, 'e') = IndexOutOfBoundsException
+     * 
+     *
+     * @param repeat  number of times to repeat delim
+     * @param padChar  character to repeat
+     * @return String with repeated character
+     * @throws IndexOutOfBoundsException if repeat < 0
+     */
+    private static String padding(int repeat, char padChar) {
+        // be careful of synchronization in this method
+        // we are assuming that get and set from an array index is atomic
+        String pad = PADDING[padChar];
+        if (pad == null) {
+            pad = String.valueOf(padChar);
+        }
+        while (pad.length() < repeat) {
+            pad = pad.concat(pad);
+        }
+        PADDING[padChar] = pad;
+        return pad.substring(0, repeat);
+    }
+
+    /**
+     * Right pad a String with spaces (' ').
+     *
+     * The String is padded to the size of size.
+     * 
+     * 
+     * StringUtils.rightPad(null, *)   = null
+     * StringUtils.rightPad("", 3)     = "   "
+     * StringUtils.rightPad("bat", 3)  = "bat"
+     * StringUtils.rightPad("bat", 5)  = "bat  "
+     * StringUtils.rightPad("bat", 1)  = "bat"
+     * StringUtils.rightPad("bat", -1) = "bat"
+     * 
+     *
+     * @param str  the String to pad out, may be null
+     * @param size  the size to pad to
+     * @return right padded String or original String if no padding is necessary,
+     *  null if null String input
+     */
+    public static String rightPad(String str, int size) {
+        return rightPad(str, size, ' ');
+    }
+
+    /**
+     * Right pad a String with a specified character.
+     *
+     * The String is padded to the size of size.
+     *
+     * 
+     * StringUtils.rightPad(null, *, *)     = null
+     * StringUtils.rightPad("", 3, 'z')     = "zzz"
+     * StringUtils.rightPad("bat", 3, 'z')  = "bat"
+     * StringUtils.rightPad("bat", 5, 'z')  = "batzz"
+     * StringUtils.rightPad("bat", 1, 'z')  = "bat"
+     * StringUtils.rightPad("bat", -1, 'z') = "bat"
+     * 
+     *
+     * @param str  the String to pad out, may be null
+     * @param size  the size to pad to
+     * @param padChar  the character to pad with
+     * @return right padded String or original String if no padding is necessary,
+     *  null if null String input
+     * @since 2.0
+     */
+    public static String rightPad(String str, int size, char padChar) {
+        if (str == null) {
+            return null;
+        }
+        int pads = size - str.length();
+        if (pads <= 0) {
+            return str; // returns original String when possible
+        }
+        if (pads > PAD_LIMIT) {
+            return rightPad(str, size, String.valueOf(padChar));
+        }
+        return str.concat(padding(pads, padChar));
+    }
+
+    /**
+     * Right pad a String with a specified String.
+     *
+     * The String is padded to the size of size.
+     *
+     * 
+     * StringUtils.rightPad(null, *, *)      = null
+     * StringUtils.rightPad("", 3, "z")      = "zzz"
+     * StringUtils.rightPad("bat", 3, "yz")  = "bat"
+     * StringUtils.rightPad("bat", 5, "yz")  = "batyz"
+     * StringUtils.rightPad("bat", 8, "yz")  = "batyzyzy"
+     * StringUtils.rightPad("bat", 1, "yz")  = "bat"
+     * StringUtils.rightPad("bat", -1, "yz") = "bat"
+     * StringUtils.rightPad("bat", 5, null)  = "bat  "
+     * StringUtils.rightPad("bat", 5, "")    = "bat  "
+     * 
+     *
+     * @param str  the String to pad out, may be null
+     * @param size  the size to pad to
+     * @param padStr  the String to pad with, null or empty treated as single space
+     * @return right padded String or original String if no padding is necessary,
+     *  null if null String input
+     */
+    public static String rightPad(String str, int size, String padStr) {
+        if (str == null) {
+            return null;
+        }
+        if (padStr == null || padStr.length() == 0) {
+            padStr = " ";
+        }
+        int padLen = padStr.length();
+        int strLen = str.length();
+        int pads = size - strLen;
+        if (pads <= 0) {
+            return str; // returns original String when possible
+        }
+        if (padLen == 1 && pads <= PAD_LIMIT) {
+            return rightPad(str, size, padStr.charAt(0));
+        }
+        
+        if (pads == padLen) {
+            return str.concat(padStr);
+        } else if (pads < padLen) {
+            return str.concat(padStr.substring(0, pads));
+        } else {
+            char[] padding = new char[pads];
+            char[] padChars = padStr.toCharArray();
+            for (int i = 0; i < pads; i++) {
+                padding[i] = padChars[i % padLen];
+            }
+            return str.concat(new String(padding));
+        }
+    }
+
+    /**
+     * Left pad a String with spaces (' ').
+     *
+     * The String is padded to the size of size.
+     *
+     * 
+     * StringUtils.leftPad(null, *)   = null
+     * StringUtils.leftPad("", 3)     = "   "
+     * StringUtils.leftPad("bat", 3)  = "bat"
+     * StringUtils.leftPad("bat", 5)  = "  bat"
+     * StringUtils.leftPad("bat", 1)  = "bat"
+     * StringUtils.leftPad("bat", -1) = "bat"
+     * 
+     *
+     * @param str  the String to pad out, may be null
+     * @param size  the size to pad to
+     * @return left padded String or original String if no padding is necessary,
+     *  null if null String input
+     */
+    public static String leftPad(String str, int size) {
+        return leftPad(str, size, ' ');        
+    }
+
+    /**
+     * Left pad a String with a specified character.
+     *
+     * Pad to a size of size.
+     *
+     * 
+     * StringUtils.leftPad(null, *, *)     = null
+     * StringUtils.leftPad("", 3, 'z')     = "zzz"
+     * StringUtils.leftPad("bat", 3, 'z')  = "bat"
+     * StringUtils.leftPad("bat", 5, 'z')  = "zzbat"
+     * StringUtils.leftPad("bat", 1, 'z')  = "bat"
+     * StringUtils.leftPad("bat", -1, 'z') = "bat"
+     * 
+     *
+     * @param str  the String to pad out, may be null
+     * @param size  the size to pad to
+     * @param padChar  the character to pad with
+     * @return left padded String or original String if no padding is necessary,
+     *  null if null String input
+     * @since 2.0
+     */
+    public static String leftPad(String str, int size, char padChar) {
+        if (str == null) {
+            return null;
+        }
+        int pads = size - str.length();
+        if (pads <= 0) {
+            return str; // returns original String when possible
+        }
+        if (pads > PAD_LIMIT) {
+            return leftPad(str, size, String.valueOf(padChar));
+        }
+        return padding(pads, padChar).concat(str);
+    }
+
+    /**
+     * Left pad a String with a specified String.
+     *
+     * Pad to a size of size.
+     *
+     * 
+     * StringUtils.leftPad(null, *, *)      = null
+     * StringUtils.leftPad("", 3, "z")      = "zzz"
+     * StringUtils.leftPad("bat", 3, "yz")  = "bat"
+     * StringUtils.leftPad("bat", 5, "yz")  = "yzbat"
+     * StringUtils.leftPad("bat", 8, "yz")  = "yzyzybat"
+     * StringUtils.leftPad("bat", 1, "yz")  = "bat"
+     * StringUtils.leftPad("bat", -1, "yz") = "bat"
+     * StringUtils.leftPad("bat", 5, null)  = "  bat"
+     * StringUtils.leftPad("bat", 5, "")    = "  bat"
+     * 
+     *
+     * @param str  the String to pad out, may be null
+     * @param size  the size to pad to
+     * @param padStr  the String to pad with, null or empty treated as single space
+     * @return left padded String or original String if no padding is necessary,
+     *  null if null String input
+     */
+    public static String leftPad(String str, int size, String padStr) {
+        if (str == null) {
+            return null;
+        }
+        if (padStr == null || padStr.length() == 0) {
+            padStr = " ";
+        }
+        int padLen = padStr.length();
+        int strLen = str.length();
+        int pads = size - strLen;
+        if (pads <= 0) {
+            return str; // returns original String when possible
+        }
+        if (padLen == 1 && pads <= PAD_LIMIT) {
+            return leftPad(str, size, padStr.charAt(0));
+        }
+        
+        if (pads == padLen) {
+            return padStr.concat(str);
+        } else if (pads < padLen) {
+            return padStr.substring(0, pads).concat(str);
+        } else {
+            char[] padding = new char[pads];
+            char[] padChars = padStr.toCharArray();
+            for (int i = 0; i < pads; i++) {
+                padding[i] = padChars[i % padLen];
+            }
+            return new String(padding).concat(str);
+        }
+    }
+
+    // Centering
+    //-----------------------------------------------------------------------
+    /**
+     * Centers a String in a larger String of size size
+     * using the space character (' ').
+     * 
+     * 
If the size is less than the String length, the String is returned.
+     * A null String returns null.
+     * A negative size is treated as zero.
+     *
+     * Equivalent to center(str, size, " ").
+     *
+     * 
+     * StringUtils.center(null, *)   = null
+     * StringUtils.center("", 4)     = "    "
+     * StringUtils.center("ab", -1)  = "ab"
+     * StringUtils.center("ab", 4)   = " ab "
+     * StringUtils.center("abcd", 2) = "abcd"
+     * StringUtils.center("a", 4)    = " a  "
+     * 
+     * 
+     * @param str  the String to center, may be null
+     * @param size  the int size of new String, negative treated as zero
+     * @return centered String, null if null String input
+     */
+    public static String center(String str, int size) {
+        return center(str, size, ' ');
+    }
+
+    /**
+     * Centers a String in a larger String of size size.
+     * Uses a supplied character as the value to pad the String with.
+     *
+     * If the size is less than the String length, the String is returned.
+     * A null String returns null.
+     * A negative size is treated as zero.
+     *
+     * 
+     * StringUtils.center(null, *, *)     = null
+     * StringUtils.center("", 4, ' ')     = "    "
+     * StringUtils.center("ab", -1, ' ')  = "ab"
+     * StringUtils.center("ab", 4, ' ')   = " ab"
+     * StringUtils.center("abcd", 2, ' ') = "abcd"
+     * StringUtils.center("a", 4, ' ')    = " a  "
+     * StringUtils.center("a", 4, 'y')    = "yayy"
+     * 
+     * 
+     * @param str  the String to center, may be null
+     * @param size  the int size of new String, negative treated as zero
+     * @param padChar  the character to pad the new String with
+     * @return centered String, null if null String input
+     * @since 2.0
+     */
+    public static String center(String str, int size, char padChar) {
+        if (str == null || size <= 0) {
+            return str;
+        }
+        int strLen = str.length();
+        int pads = size - strLen;
+        if (pads <= 0) {
+            return str;
+        }
+        str = leftPad(str, strLen + pads / 2, padChar);
+        str = rightPad(str, size, padChar);
+        return str;
+    }
+
+    /**
+     * Centers a String in a larger String of size size.
+     * Uses a supplied String as the value to pad the String with.
+     *
+     * If the size is less than the String length, the String is returned.
+     * A null String returns null.
+     * A negative size is treated as zero.
+     *
+     * 
+     * StringUtils.center(null, *, *)     = null
+     * StringUtils.center("", 4, " ")     = "    "
+     * StringUtils.center("ab", -1, " ")  = "ab"
+     * StringUtils.center("ab", 4, " ")   = " ab"
+     * StringUtils.center("abcd", 2, " ") = "abcd"
+     * StringUtils.center("a", 4, " ")    = " a  "
+     * StringUtils.center("a", 4, "yz")   = "yayz"
+     * StringUtils.center("abc", 7, null) = "  abc  "
+     * StringUtils.center("abc", 7, "")   = "  abc  "
+     * 
+     * 
+     * @param str  the String to center, may be null
+     * @param size  the int size of new String, negative treated as zero
+     * @param padStr  the String to pad the new String with, must not be null or empty
+     * @return centered String, null if null String input
+     * @throws IllegalArgumentException if padStr is null or empty
+     */
+    public static String center(String str, int size, String padStr) {
+        if (str == null || size <= 0) {
+            return str;
+        }
+        if (padStr == null || padStr.length() == 0) {
+            padStr = " ";
+        }
+        int strLen = str.length();
+        int pads = size - strLen;
+        if (pads <= 0) {
+            return str;
+        }
+        str = leftPad(str, strLen + pads / 2, padStr);
+        str = rightPad(str, size, padStr);
+        return str;
+    }
+
+    // Case conversion
+    //-----------------------------------------------------------------------
+    /**
+     * Converts a String to upper case as per {@link String#toUpperCase()}.
+     * 
+     * A null input String returns null.
+     * 
+     * 
+     * StringUtils.upperCase(null)  = null
+     * StringUtils.upperCase("")    = ""
+     * StringUtils.upperCase("aBc") = "ABC"
+     * 
+     * 
+     * @param str  the String to upper case, may be null
+     * @return the upper cased String, null if null String input
+     */
+    public static String upperCase(String str) {
+        if (str == null) {
+            return null;
+        }
+        return str.toUpperCase();
+    }
+
+    /**
+     * Converts a String to lower case as per {@link String#toLowerCase()}.
+     * 
+     * A null input String returns null.
+     * 
+     * 
+     * StringUtils.lowerCase(null)  = null
+     * StringUtils.lowerCase("")    = ""
+     * StringUtils.lowerCase("aBc") = "abc"
+     * 
+     * 
+     * @param str  the String to lower case, may be null
+     * @return the lower cased String, null if null String input
+     */
+    public static String lowerCase(String str) {
+        if (str == null) {
+            return null;
+        }
+        return str.toLowerCase();
+    }
+
+    /**
+     * Capitalizes a String changing the first letter to title case as
+     * per {@link Character#toTitleCase(char)}. No other letters are changed.
+     * 
+     * For a word based alorithm, see {@link WordUtils#capitalize(String)}.
+     * A null input String returns null.
+     * 
+     * 
+     * StringUtils.capitalize(null)  = null
+     * StringUtils.capitalize("")    = ""
+     * StringUtils.capitalize("cat") = "Cat"
+     * StringUtils.capitalize("cAt") = "CAt"
+     * 
+     * 
+     * @param str  the String to capitalize, may be null
+     * @return the capitalized String, null if null String input
+     * @see WordUtils#capitalize(String)
+     * @see #uncapitalize(String)
+     * @since 2.0
+     */
+    public static String capitalize(String str) {
+        int strLen;
+        if (str == null || (strLen = str.length()) == 0) {
+            return str;
+        }
+        return new StringBuffer(strLen)
+            .append(Character.toTitleCase(str.charAt(0)))
+            .append(str.substring(1))
+            .toString();
+    }
+
+    /**
+     * Capitalizes a String changing the first letter to title case as
+     * per {@link Character#toTitleCase(char)}. No other letters are changed.
+     * 
+     * @param str  the String to capitalize, may be null
+     * @return the capitalized String, null if null String input
+     * @deprecated Use the standardly named {@link #capitalize(String)}.
+     *             Method will be removed in Commons Lang 3.0.
+     */
+    public static String capitalise(String str) {
+        return capitalize(str);
+    }
+
+    /**
+     * Uncapitalizes a String changing the first letter to title case as
+     * per {@link Character#toLowerCase(char)}. No other letters are changed.
+     * 
+     * For a word based alorithm, see {@link WordUtils#uncapitalize(String)}.
+     * A null input String returns null.
+     * 
+     * 
+     * StringUtils.uncapitalize(null)  = null
+     * StringUtils.uncapitalize("")    = ""
+     * StringUtils.uncapitalize("Cat") = "cat"
+     * StringUtils.uncapitalize("CAT") = "cAT"
+     * 
+     * 
+     * @param str  the String to uncapitalize, may be null
+     * @return the uncapitalized String, null if null String input
+     * @see WordUtils#uncapitalize(String)
+     * @see #capitalize(String)
+     * @since 2.0
+     */
+    public static String uncapitalize(String str) {
+        int strLen;
+        if (str == null || (strLen = str.length()) == 0) {
+            return str;
+        }
+        return new StringBuffer(strLen)
+            .append(Character.toLowerCase(str.charAt(0)))
+            .append(str.substring(1))
+            .toString();
+    }
+
+    /**
+     * Uncapitalizes a String changing the first letter to title case as
+     * per {@link Character#toLowerCase(char)}. No other letters are changed.
+     * 
+     * @param str  the String to uncapitalize, may be null
+     * @return the uncapitalized String, null if null String input
+     * @deprecated Use the standardly named {@link #uncapitalize(String)}.
+     *             Method will be removed in Commons Lang 3.0.
+     */
+    public static String uncapitalise(String str) {
+        return uncapitalize(str);
+    }
+
+    /**
+     * Swaps the case of a String changing upper and title case to
+     * lower case, and lower case to upper case.
+     * 
+     * 
+     *  - Upper case character converts to Lower case
 
+     *  - Title case character converts to Lower case
 
+     *  - Lower case character converts to Upper case
 
+     * 
+     * 
+     * For a word based alorithm, see {@link WordUtils#swapCase(String)}.
+     * A null input String returns null.
+     * 
+     * 
+     * StringUtils.swapCase(null)                 = null
+     * StringUtils.swapCase("")                   = ""
+     * StringUtils.swapCase("The dog has a BONE") = "tHE DOG HAS A bone"
+     * 
+     * 
+     * NOTE: This method changed in Lang version 2.0.
+     * It no longer performs a word based alorithm.
+     * If you only use ASCII, you will notice no change.
+     * That functionality is available in WordUtils.
+     * 
+     * @param str  the String to swap case, may be null
+     * @return the changed String, null if null String input
+     */
+    public static String swapCase(String str) {
+        int strLen;
+        if (str == null || (strLen = str.length()) == 0) {
+            return str;
+        }
+        StringBuffer buffer = new StringBuffer(strLen);
+
+        char ch = 0;
+        for (int i = 0; i < strLen; i++) {
+            ch = str.charAt(i);
+            if (Character.isUpperCase(ch)) {
+                ch = Character.toLowerCase(ch);
+            } else if (Character.isTitleCase(ch)) {
+                ch = Character.toLowerCase(ch);
+            } else if (Character.isLowerCase(ch)) {
+                ch = Character.toUpperCase(ch);
+            }
+            buffer.append(ch);
+        }
+        return buffer.toString();
+    }
+
+    /**
+     * Capitalizes all the whitespace separated words in a String.
+     * Only the first letter of each word is changed.
+     *
+     * Whitespace is defined by {@link Character#isWhitespace(char)}.
+     * A null input String returns null.
+     *
+     * @param str  the String to capitalize, may be null
+     * @return capitalized String, null if null String input
+     * @deprecated Use the relocated {@link WordUtils#capitalize(String)}.
+     *             Method will be removed in Commons Lang 3.0.
+     */
+    public static String capitaliseAllWords(String str) {
+        return WordUtils.capitalize(str);
+    }
+
+    // Count matches
+    //-----------------------------------------------------------------------
+    /**
+     * Counts how many times the substring appears in the larger String.
+     *
+     * A null or empty ("") String input returns 0.
+     * 
+     * 
+     * StringUtils.countMatches(null, *)       = 0
+     * StringUtils.countMatches("", *)         = 0
+     * StringUtils.countMatches("abba", null)  = 0
+     * StringUtils.countMatches("abba", "")    = 0
+     * StringUtils.countMatches("abba", "a")   = 2
+     * StringUtils.countMatches("abba", "ab")  = 1
+     * StringUtils.countMatches("abba", "xxx") = 0
+     * 
+     *
+     * @param str  the String to check, may be null
+     * @param sub  the substring to count, may be null
+     * @return the number of occurances, 0 if either String is null
+     */
+    public static int countMatches(String str, String sub) {
+        if (str == null || str.length() == 0 || sub == null || sub.length() == 0) {
+            return 0;
+        }
+        int count = 0;
+        int idx = 0;
+        while ((idx = str.indexOf(sub, idx)) != -1) {
+            count++;
+            idx += sub.length();
+        }
+        return count;
+    }
+
+    // Character Tests
+    //-----------------------------------------------------------------------
+    /**
+     * Checks if the String contains only unicode letters.
+     *
+     * null will return false.
+     * An empty String ("") will return true.
+     * 
+     * 
+     * StringUtils.isAlpha(null)   = false
+     * StringUtils.isAlpha("")     = true
+     * StringUtils.isAlpha("  ")   = false
+     * StringUtils.isAlpha("abc")  = true
+     * StringUtils.isAlpha("ab2c") = false
+     * StringUtils.isAlpha("ab-c") = false
+     * 
+     *
+     * @param str  the String to check, may be null
+     * @return true if only contains letters, and is non-null
+     */
+    public static boolean isAlpha(String str) {
+        if (str == null) {
+            return false;
+        }
+        int sz = str.length();
+        for (int i = 0; i < sz; i++) {
+            if (Character.isLetter(str.charAt(i)) == false) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Checks if the String contains only unicode letters and
+     * space (' ').
+     *
+     * null will return false
+     * An empty String ("") will return true.
+     * 
+     * 
+     * StringUtils.isAlphaSpace(null)   = false
+     * StringUtils.isAlphaSpace("")     = true
+     * StringUtils.isAlphaSpace("  ")   = true
+     * StringUtils.isAlphaSpace("abc")  = true
+     * StringUtils.isAlphaSpace("ab c") = true
+     * StringUtils.isAlphaSpace("ab2c") = false
+     * StringUtils.isAlphaSpace("ab-c") = false
+     * 
+     *
+     * @param str  the String to check, may be null
+     * @return true if only contains letters and space,
+     *  and is non-null
+     */
+    public static boolean isAlphaSpace(String str) {
+        if (str == null) {
+            return false;
+        }
+        int sz = str.length();
+        for (int i = 0; i < sz; i++) {
+            if ((Character.isLetter(str.charAt(i)) == false) &&
+                (str.charAt(i) != ' ')) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Checks if the String contains only unicode letters or digits.
+     *
+     * null will return false.
+     * An empty String ("") will return true.
+     * 
+     * 
+     * StringUtils.isAlphanumeric(null)   = false
+     * StringUtils.isAlphanumeric("")     = true
+     * StringUtils.isAlphanumeric("  ")   = false
+     * StringUtils.isAlphanumeric("abc")  = true
+     * StringUtils.isAlphanumeric("ab c") = false
+     * StringUtils.isAlphanumeric("ab2c") = true
+     * StringUtils.isAlphanumeric("ab-c") = false
+     * 
+     *
+     * @param str  the String to check, may be null
+     * @return true if only contains letters or digits,
+     *  and is non-null
+     */
+    public static boolean isAlphanumeric(String str) {
+        if (str == null) {
+            return false;
+        }
+        int sz = str.length();
+        for (int i = 0; i < sz; i++) {
+            if (Character.isLetterOrDigit(str.charAt(i)) == false) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Checks if the String contains only unicode letters, digits
+     * or space (' ').
+     *
+     * null will return false.
+     * An empty String ("") will return true.
+     * 
+     * 
+     * StringUtils.isAlphanumeric(null)   = false
+     * StringUtils.isAlphanumeric("")     = true
+     * StringUtils.isAlphanumeric("  ")   = true
+     * StringUtils.isAlphanumeric("abc")  = true
+     * StringUtils.isAlphanumeric("ab c") = true
+     * StringUtils.isAlphanumeric("ab2c") = true
+     * StringUtils.isAlphanumeric("ab-c") = false
+     * 
+     *
+     * @param str  the String to check, may be null
+     * @return true if only contains letters, digits or space,
+     *  and is non-null
+     */
+    public static boolean isAlphanumericSpace(String str) {
+        if (str == null) {
+            return false;
+        }
+        int sz = str.length();
+        for (int i = 0; i < sz; i++) {
+            if ((Character.isLetterOrDigit(str.charAt(i)) == false) &&
+                (str.charAt(i) != ' ')) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Checks if the String contains only unicode digits.
+     * A decimal point is not a unicode digit and returns false.
+     *
+     * null will return false.
+     * An empty String ("") will return true.
+     * 
+     * 
+     * StringUtils.isNumeric(null)   = false
+     * StringUtils.isNumeric("")     = true
+     * StringUtils.isNumeric("  ")   = false
+     * StringUtils.isNumeric("123")  = true
+     * StringUtils.isNumeric("12 3") = false
+     * StringUtils.isNumeric("ab2c") = false
+     * StringUtils.isNumeric("12-3") = false
+     * StringUtils.isNumeric("12.3") = false
+     * 
+     *
+     * @param str  the String to check, may be null
+     * @return true if only contains digits, and is non-null
+     */
+    public static boolean isNumeric(String str) {
+        if (str == null) {
+            return false;
+        }
+        int sz = str.length();
+        for (int i = 0; i < sz; i++) {
+            if (Character.isDigit(str.charAt(i)) == false) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Checks if the String contains only unicode digits or space
+     * (' ').
+     * A decimal point is not a unicode digit and returns false.
+     *
+     * null will return false.
+     * An empty String ("") will return true.
+     * 
+     * 
+     * StringUtils.isNumeric(null)   = false
+     * StringUtils.isNumeric("")     = true
+     * StringUtils.isNumeric("  ")   = true
+     * StringUtils.isNumeric("123")  = true
+     * StringUtils.isNumeric("12 3") = true
+     * StringUtils.isNumeric("ab2c") = false
+     * StringUtils.isNumeric("12-3") = false
+     * StringUtils.isNumeric("12.3") = false
+     * 
+     *
+     * @param str  the String to check, may be null
+     * @return true if only contains digits or space,
+     *  and is non-null
+     */
+    public static boolean isNumericSpace(String str) {
+        if (str == null) {
+            return false;
+        }
+        int sz = str.length();
+        for (int i = 0; i < sz; i++) {
+            if ((Character.isDigit(str.charAt(i)) == false) &&
+                (str.charAt(i) != ' ')) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Checks if the String contains only whitespace.
+     *
+     * null will return false.
+     * An empty String ("") will return true.
+     * 
+     * 
+     * StringUtils.isWhitespace(null)   = false
+     * StringUtils.isWhitespace("")     = true
+     * StringUtils.isWhitespace("  ")   = true
+     * StringUtils.isWhitespace("abc")  = false
+     * StringUtils.isWhitespace("ab2c") = false
+     * StringUtils.isWhitespace("ab-c") = false
+     * 
+     *
+     * @param str  the String to check, may be null
+     * @return true if only contains whitespace, and is non-null
+     * @since 2.0
+     */
+    public static boolean isWhitespace(String str) {
+        if (str == null) {
+            return false;
+        }
+        int sz = str.length();
+        for (int i = 0; i < sz; i++) {
+            if ((Character.isWhitespace(str.charAt(i)) == false) ) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    // Defaults
+    //-----------------------------------------------------------------------
+    /**
+     * Returns either the passed in String, 
+     * or if the String is null, an empty String ("").
+     * 
+     * 
+     * StringUtils.defaultString(null)  = ""
+     * StringUtils.defaultString("")    = ""
+     * StringUtils.defaultString("bat") = "bat"
+     * 
+     * 
+     * @see ObjectUtils#toString(Object)
+     * @see String#valueOf(Object)
+     * @param str  the String to check, may be null
+     * @return the passed in String, or the empty String if it
+     *  was null
+     */
+    public static String defaultString(String str) {
+        return (str == null ? EMPTY : str);
+    }
+
+    /**
+     * Returns either the passed in String, 
+     * or if the String is null, an empty String ("").
+     * 
+     * 
+     * StringUtils.defaultString(null, "null")  = "null"
+     * StringUtils.defaultString("", "null")    = ""
+     * StringUtils.defaultString("bat", "null") = "bat"
+     * 
+     * 
+     * @see ObjectUtils#toString(Object,String)
+     * @see String#valueOf(Object)
+     * @param str  the String to check, may be null
+     * @param defaultStr  the default String to return 
+     *  if the input is null, may be null
+     * @return the passed in String, or the default if it was null
+     */
+    public static String defaultString(String str, String defaultStr) {
+        return (str == null ? defaultStr : str);
+    }
+
+    // Reversing
+    //-----------------------------------------------------------------------
+    /**
+     * Reverses a String as per {@link StringBuffer#reverse()}.
+     *
+     *     String returns null.
+     * 
+     * 
+     * StringUtils.reverse(null)  = null
+     * StringUtils.reverse("")    = ""
+     * StringUtils.reverse("bat") = "tab"
+     * 
+     * 
+     * @param str  the String to reverse, may be null
+     * @return the reversed String, null if null String input
+     */
+    public static String reverse(String str) {
+        if (str == null) {
+            return null;
+        }
+        return new StringBuffer(str).reverse().toString();
+    }
+
+    /**
+     * Reverses a String that is delimited by a specific character.
+     *
+     * The Strings between the delimiters are not reversed.
+     * Thus java.lang.String becomes String.lang.java (if the delimiter
+     * is '.').
+     * 
+     * 
+     * StringUtils.reverseDelimited(null, *)      = null
+     * StringUtils.reverseDelimited("", *)        = ""
+     * StringUtils.reverseDelimited("a.b.c", 'x') = "a.b.c"
+     * StringUtils.reverseDelimited("a.b.c", ".") = "c.b.a"
+     * 
+     * 
+     * @param str  the String to reverse, may be null
+     * @param separatorChar  the separator character to use
+     * @return the reversed String, null if null String input
+     * @since 2.0
+     */
+    public static String reverseDelimited(String str, char separatorChar) {
+        if (str == null) {
+            return null;
+        }
+        // could implement manually, but simple way is to reuse other, 
+        // probably slower, methods.
+        String[] strs = split(str, separatorChar);
+        ArrayUtils.reverse(strs);
+        return join(strs, separatorChar);
+    }
+
+    /**
+     * Reverses a String that is delimited by a specific character.
+     *
+     * The Strings between the delimiters are not reversed.
+     * Thus java.lang.String becomes String.lang.java (if the delimiter
+     * is ".").
+     * 
+     * 
+     * StringUtils.reverseDelimitedString(null, *)       = null
+     * StringUtils.reverseDelimitedString("",*)          = ""
+     * StringUtils.reverseDelimitedString("a.b.c", null) = "a.b.c"
+     * StringUtils.reverseDelimitedString("a.b.c", ".")  = "c.b.a"
+     * 
+     * 
+     * @param str  the String to reverse, may be null
+     * @param separatorChars  the separator characters to use, null treated as whitespace
+     * @return the reversed String, null if null String input
+     * @deprecated Use {@link #reverseDelimited(String, char)} instead.
+     *      This method is broken as the join doesn't know which char to use.
+     *      Method will be removed in Commons Lang 3.0.
+     * 
+     */
+    public static String reverseDelimitedString(String str, String separatorChars) {
+        if (str == null) {
+            return null;
+        }
+        // could implement manually, but simple way is to reuse other, 
+        // probably slower, methods.
+        String[] strs = split(str, separatorChars);
+        ArrayUtils.reverse(strs);
+        if (separatorChars == null) {
+            return join(strs, ' ');
+        }
+        return join(strs, separatorChars);
+    }
+
+    // Abbreviating
+    //-----------------------------------------------------------------------
+    /**
+     * Abbreviates a String using ellipses. This will turn 
+     * "Now is the time for all good men" into "Now is the time for..."
+     *
+     * Specifically:
+     * 
+     *   - If 
str is less than maxWidth characters
+     *       long, return it. 
+     *   - Else abbreviate it to 
(substring(str, 0, max-3) + "..."). 
+     *   - If 
maxWidth is less than 4, throw an
+     *       IllegalArgumentException. 
+     *   - In no case will it return a String of length greater than
+     *       
maxWidth. 
+     * 
+     * 
+     *
+     * 
+     * StringUtils.abbreviate(null, *)      = null
+     * StringUtils.abbreviate("", 4)        = ""
+     * StringUtils.abbreviate("abcdefg", 6) = "abc..."
+     * StringUtils.abbreviate("abcdefg", 7) = "abcdefg"
+     * StringUtils.abbreviate("abcdefg", 8) = "abcdefg"
+     * StringUtils.abbreviate("abcdefg", 4) = "a..."
+     * StringUtils.abbreviate("abcdefg", 3) = IllegalArgumentException
+     * 
+     *
+     * @param str  the String to check, may be null
+     * @param maxWidth  maximum length of result String, must be at least 4
+     * @return abbreviated String, null if null String input
+     * @throws IllegalArgumentException if the width is too small
+     * @since 2.0
+     */
+    public static String abbreviate(String str, int maxWidth) {
+        return abbreviate(str, 0, maxWidth);
+    }
+
+    /**
+     * Abbreviates a String using ellipses. This will turn 
+     * "Now is the time for all good men" into "...is the time for..."
+     *
+     * Works like abbreviate(String, int), but allows you to specify
+     * a "left edge" offset.  Note that this left edge is not necessarily going to
+     * be the leftmost character in the result, or the first character following the
+     * ellipses, but it will appear somewhere in the result.
+     *
+     * 
In no case will it return a String of length greater than
+     * maxWidth.
+     *
+     * 
+     * StringUtils.abbreviate(null, *, *)                = null
+     * StringUtils.abbreviate("", 0, 4)                  = ""
+     * StringUtils.abbreviate("abcdefghijklmno", -1, 10) = "abcdefg..."
+     * StringUtils.abbreviate("abcdefghijklmno", 0, 10)  = "abcdefg..."
+     * StringUtils.abbreviate("abcdefghijklmno", 1, 10)  = "abcdefg..."
+     * StringUtils.abbreviate("abcdefghijklmno", 4, 10)  = "abcdefg..."
+     * StringUtils.abbreviate("abcdefghijklmno", 5, 10)  = "...fghi..."
+     * StringUtils.abbreviate("abcdefghijklmno", 6, 10)  = "...ghij..."
+     * StringUtils.abbreviate("abcdefghijklmno", 8, 10)  = "...ijklmno"
+     * StringUtils.abbreviate("abcdefghijklmno", 10, 10) = "...ijklmno"
+     * StringUtils.abbreviate("abcdefghijklmno", 12, 10) = "...ijklmno"
+     * StringUtils.abbreviate("abcdefghij", 0, 3)        = IllegalArgumentException
+     * StringUtils.abbreviate("abcdefghij", 5, 6)        = IllegalArgumentException
+     * 
+     *
+     * @param str  the String to check, may be null
+     * @param offset  left edge of source String
+     * @param maxWidth  maximum length of result String, must be at least 4
+     * @return abbreviated String, null if null String input
+     * @throws IllegalArgumentException if the width is too small
+     * @since 2.0
+     */
+    public static String abbreviate(String str, int offset, int maxWidth) {
+        if (str == null) {
+            return null;
+        }
+        if (maxWidth < 4) {
+            throw new IllegalArgumentException("Minimum abbreviation width is 4");
+        }
+        if (str.length() <= maxWidth) {
+            return str;
+        }
+        if (offset > str.length()) {
+            offset = str.length();
+        }
+        if ((str.length() - offset) < (maxWidth - 3)) {
+            offset = str.length() - (maxWidth - 3);
+        }
+        if (offset <= 4) {
+            return str.substring(0, maxWidth - 3) + "...";
+        }
+        if (maxWidth < 7) {
+            throw new IllegalArgumentException("Minimum abbreviation width with offset is 7");
+        }
+        if ((offset + (maxWidth - 3)) < str.length()) {
+            return "..." + abbreviate(str.substring(offset), maxWidth - 3);
+        }
+        return "..." + str.substring(str.length() - (maxWidth - 3));
+    }
+
+    // Difference
+    //-----------------------------------------------------------------------
+    /**
+     * Compares two Strings, and returns the portion where they differ.
+     * (More precisely, return the remainder of the second String,
+     * starting from where it's different from the first.)
+     *
+     * For example,
+     * difference("i am a machine", "i am a robot") -> "robot".
+     *
+     * 
+     * StringUtils.difference(null, null) = null
+     * StringUtils.difference("", "") = ""
+     * StringUtils.difference("", "abc") = "abc"
+     * StringUtils.difference("abc", "") = ""
+     * StringUtils.difference("abc", "abc") = ""
+     * StringUtils.difference("ab", "abxyz") = "xyz"
+     * StringUtils.difference("abcde", "abxyz") = "xyz"
+     * StringUtils.difference("abcde", "xyz") = "xyz"
+     * 
+     *
+     * @param str1  the first String, may be null
+     * @param str2  the second String, may be null
+     * @return the portion of str2 where it differs from str1; returns the 
+     * empty String if they are equal
+     * @since 2.0
+     */
+    public static String difference(String str1, String str2) {
+        if (str1 == null) {
+            return str2;
+        }
+        if (str2 == null) {
+            return str1;
+        }
+        int at = indexOfDifference(str1, str2);
+        if (at == -1) {
+            return EMPTY;
+        }
+        return str2.substring(at);
+    }
+
+    /**
+     * Compares two Strings, and returns the index at which the
+     * Strings begin to differ.
+     * 
+     * For example, 
+     * indexOfDifference("i am a machine", "i am a robot") -> 7
+     *
+     * 
+     * StringUtils.indexOfDifference(null, null) = -1
+     * StringUtils.indexOfDifference("", "") = -1
+     * StringUtils.indexOfDifference("", "abc") = 0
+     * StringUtils.indexOfDifference("abc", "") = 0
+     * StringUtils.indexOfDifference("abc", "abc") = -1
+     * StringUtils.indexOfDifference("ab", "abxyz") = 2
+     * StringUtils.indexOfDifference("abcde", "abxyz") = 2
+     * StringUtils.indexOfDifference("abcde", "xyz") = 0
+     * 
+     *
+     * @param str1  the first String, may be null
+     * @param str2  the second String, may be null
+     * @return the index where str2 and str1 begin to differ; -1 if they are equal
+     * @since 2.0
+     */
+    public static int indexOfDifference(String str1, String str2) {
+        if (str1 == str2) {
+            return -1;
+        }
+        if (str1 == null || str2 == null) {
+            return 0;
+        }
+        int i;
+        for (i = 0; i < str1.length() && i < str2.length(); ++i) {
+            if (str1.charAt(i) != str2.charAt(i)) {
+                break;
+            }
+        }
+        if (i < str2.length() || i < str1.length()) {
+            return i;
+        }
+        return -1;
+    }
+
+
+    // Misc
+    //-----------------------------------------------------------------------
+    /**
+     * Find the Levenshtein distance between two Strings.
+     *
+     * This is the number of changes needed to change one String into
+     * another, where each change is a single character modification (deletion, 
+     * insertion or substitution).
+     *
+     * This implementation of the Levenshtein distance algorithm
+     * is from http://www.merriampark.com/ld.htm
+     *
+     * 
+     * StringUtils.getLevenshteinDistance(null, *)             = IllegalArgumentException
+     * StringUtils.getLevenshteinDistance(*, null)             = IllegalArgumentException
+     * StringUtils.getLevenshteinDistance("","")               = 0
+     * StringUtils.getLevenshteinDistance("","a")              = 1
+     * StringUtils.getLevenshteinDistance("aaapppp", "")       = 7
+     * StringUtils.getLevenshteinDistance("frog", "fog")       = 1
+     * StringUtils.getLevenshteinDistance("fly", "ant")        = 3
+     * StringUtils.getLevenshteinDistance("elephant", "hippo") = 7
+     * StringUtils.getLevenshteinDistance("hippo", "elephant") = 7
+     * StringUtils.getLevenshteinDistance("hippo", "zzzzzzzz") = 8
+     * StringUtils.getLevenshteinDistance("hello", "hallo")    = 1
+     * 
+     * 
+     * @param s  the first String, must not be null
+     * @param t  the second String, must not be null
+     * @return result distance
+     * @throws IllegalArgumentException if either String input null
+     */
+    public static int getLevenshteinDistance(String s, String t) {
+        if (s == null || t == null) {
+            throw new IllegalArgumentException("Strings must not be null");
+        }
+        int d[][]; // matrix
+        int n; // length of s
+        int m; // length of t
+        int i; // iterates through s
+        int j; // iterates through t
+        char s_i; // ith character of s
+        char t_j; // jth character of t
+        int cost; // cost
+
+        // Step 1
+        n = s.length();
+        m = t.length();
+        if (n == 0) {
+            return m;
+        }
+        if (m == 0) {
+            return n;
+        }
+        d = new int[n + 1][m + 1];
+
+        // Step 2
+        for (i = 0; i <= n; i++) {
+            d[i][0] = i;
+        }
+
+        for (j = 0; j <= m; j++) {
+            d[0][j] = j;
+        }
+
+        // Step 3
+        for (i = 1; i <= n; i++) {
+            s_i = s.charAt(i - 1);
+
+            // Step 4
+            for (j = 1; j <= m; j++) {
+                t_j = t.charAt(j - 1);
+
+                // Step 5
+                if (s_i == t_j) {
+                    cost = 0;
+                } else {
+                    cost = 1;
+                }
+
+                // Step 6
+                d[i][j] = min(d[i - 1][j] + 1, d[i][j - 1] + 1, d[i - 1][j - 1] + cost);
+            }
+        }
+
+        // Step 7
+        return d[n][m];
+    }
+
+    /**
+     * Gets the minimum of three int values.
+     * 
+     * @param a  value 1
+     * @param b  value 2
+     * @param c  value 3
+     * @return  the smallest of the values
+     */
+    private static int min(int a, int b, int c) {
+        // Method copied from NumberUtils to avoid dependency on subpackage
+        if (b < a) {
+            a = b;
+        }
+        if (c < a) {
+            a = c;
+        }
+        return a;
+    }
+
+}
+
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/SystemUtils.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/SystemUtils.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/SystemUtils.java	30 Aug 2012 16:24:42 -0000	1.1
@@ -0,0 +1,886 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang;
+
+/**
+ * Helpers for java.lang.System.
+ * 
+ * If a system property cannot be read due to security restrictions, 
+ * the corresponding field in this class will be set to null
+ * and a message will be written to System.err.
+ *
+ * @author Based on code from Avalon Excalibur
+ * @author Based on code from Lucene
+ * @author Stephen Colebourne
+ * @author Steve Downey
+ * @author Gary Gregory
+ * @author Michael Becke
+ * @author Tetsuya Kaneuchi
+ * @since 1.0
+ * @version $Id: SystemUtils.java,v 1.1 2012/08/30 16:24:42 marcin Exp $
+ */
+public class SystemUtils {
+
+    // System property constants
+    //-----------------------------------------------------------------------
+    // These MUST be declared first. Other constants depend on this.
+    
+    /**
+     * The file.encoding System Property.
+     * File encoding, such as Cp1252.
+     * 
+     * Defaults to null if the runtime does not have
+     * security access to read this property or the property does not exist.
+     * 
+     * @since 2.0
+     * @since Java 1.2.
+     */
+    public static final String FILE_ENCODING = getSystemProperty("file.encoding");
+
+    /**
+     * The file.separator System Property.
+     * File separator ("/" on UNIX).
+     *
+     * Defaults to null if the runtime does not have
+     * security access to read this property or the property does not exist.
+     * 
+     * @since Java 1.1.
+     */
+    public static final String FILE_SEPARATOR = getSystemProperty("file.separator");
+
+    /**
+     * The java.class.path System Property. Java class path.
+     *
+     * Defaults to null if the runtime does not have
+     * security access to read this property or the property does not exist.
+     * 
+     * @since Java 1.1.
+     */
+    public static final String JAVA_CLASS_PATH = getSystemProperty("java.class.path");
+
+    /**
+     * The java.class.version System Property.
+     * Java class format version number.
+     *
+     * Defaults to null if the runtime does not have
+     * security access to read this property or the property does not exist.
+     * 
+     * @since Java 1.1.
+     */
+    public static final String JAVA_CLASS_VERSION = getSystemProperty("java.class.version");
+
+    /**
+     * The java.compiler System Property. Name of JIT compiler to use.
+     * First in JDK version 1.2. Not used in Sun JDKs after 1.2.
+     *
+     * Defaults to null if the runtime does not have
+     * security access to read this property or the property does not exist.
+     * 
+     * @since Java 1.2. Not used in Sun versions after 1.2.
+     */
+    public static final String JAVA_COMPILER = getSystemProperty("java.compiler");
+
+    /**
+     * The java.ext.dirs System Property. Path of extension directory
+     * or directories.
+     *
+     * Defaults to null if the runtime does not have
+     * security access to read this property or the property does not exist.
+     * 
+     * @since Java 1.3
+     */
+    public static final String JAVA_EXT_DIRS = getSystemProperty("java.ext.dirs");
+
+    /**
+     * The java.home System Property. Java installation directory.
+     *
+     * Defaults to null if the runtime does not have
+     * security access to read this property or the property does not exist.
+     * 
+     * @since Java 1.1
+     */
+    public static final String JAVA_HOME = getSystemProperty("java.home");
+
+    /**
+     * The java.io.tmpdir System Property. Default temp file path.
+     *
+     * Defaults to null if the runtime does not have
+     * security access to read this property or the property does not exist.
+     * 
+     * @since Java 1.2
+     */
+    public static final String JAVA_IO_TMPDIR = getSystemProperty("java.io.tmpdir");
+
+    /**
+     * The java.library.path System Property. List of paths to search
+     * when loading libraries.
+     *
+     * Defaults to null if the runtime does not have
+     * security access to read this property or the property does not exist.
+     * 
+     * @since Java 1.2
+     */
+    public static final String JAVA_LIBRARY_PATH = getSystemProperty("java.library.path");
+
+    /**
+     * The java.runtime.name System Property. Java Runtime Environment
+     * name.
+     *
+     * Defaults to null if the runtime does not have
+     * security access to read this property or the property does not exist.
+     * 
+     * @since 2.0
+     * @since Java 1.3
+     */
+    public static final String JAVA_RUNTIME_NAME = getSystemProperty("java.runtime.name");
+
+    /**
+     * The java.runtime.version System Property. Java Runtime Environment
+     * version.
+     *
+     * Defaults to null if the runtime does not have
+     * security access to read this property or the property does not exist.
+     * 
+     * @since 2.0
+     * @since Java 1.3
+     */
+    public static final String JAVA_RUNTIME_VERSION = getSystemProperty("java.runtime.version");
+
+    /**
+     * The java.specification.name System Property. Java Runtime Environment
+     * specification name.
+     *
+     * Defaults to null if the runtime does not have
+     * security access to read this property or the property does not exist.
+     * 
+     * @since Java 1.2
+     */
+    public static final String JAVA_SPECIFICATION_NAME = getSystemProperty("java.specification.name");
+
+    /**
+     * The java.specification.vendor System Property. Java Runtime Environment
+     * specification vendor.
+     *
+     * Defaults to null if the runtime does not have
+     * security access to read this property or the property does not exist.
+     * 
+     * @since Java 1.2
+     */
+    public static final String JAVA_SPECIFICATION_VENDOR = getSystemProperty("java.specification.vendor");
+
+    /**
+     * The java.specification.version System Property. Java Runtime Environment
+     * specification version.
+     *
+     * Defaults to null if the runtime does not have
+     * security access to read this property or the property does not exist.
+     * 
+     * @since Java 1.3
+     */
+    public static final String JAVA_SPECIFICATION_VERSION = getSystemProperty("java.specification.version");
+
+    /**
+     * The java.vendor System Property. Java vendor-specific string.
+     *
+     * Defaults to null if the runtime does not have
+     * security access to read this property or the property does not exist.
+     * 
+     * @since Java 1.1
+     */
+    public static final String JAVA_VENDOR = getSystemProperty("java.vendor");
+
+    /**
+     * The java.vendor.url System Property. Java vendor URL.
+     *
+     * Defaults to null if the runtime does not have
+     * security access to read this property or the property does not exist.
+      * 
+     * @since Java 1.1
+    */
+    public static final String JAVA_VENDOR_URL = getSystemProperty("java.vendor.url");
+
+    /**
+     * The java.version System Property. Java version number.
+     *
+     * Defaults to null if the runtime does not have
+     * security access to read this property or the property does not exist.
+     * 
+     * @since Java 1.1
+     */
+    public static final String JAVA_VERSION = getSystemProperty("java.version");
+
+    /**
+     * The java.vm.info System Property. Java Virtual Machine implementation
+     * info.
+     *
+     * Defaults to null if the runtime does not have
+     * security access to read this property or the property does not exist.
+     * 
+     * @since 2.0
+     * @since Java 1.2
+     */
+    public static final String JAVA_VM_INFO = getSystemProperty("java.vm.info");
+
+    /**
+     * The java.vm.name System Property. Java Virtual Machine implementation
+     * name.
+     *
+     * Defaults to null if the runtime does not have
+     * security access to read this property or the property does not exist.
+     * 
+     * @since Java 1.2
+     */
+    public static final String JAVA_VM_NAME = getSystemProperty("java.vm.name");
+
+    /**
+     * The java.vm.specification.name System Property. Java Virtual Machine
+     * specification name.
+     *
+     * Defaults to null if the runtime does not have
+     * security access to read this property or the property does not exist.
+     * 
+     * @since Java 1.2
+     */
+    public static final String JAVA_VM_SPECIFICATION_NAME = getSystemProperty("java.vm.specification.name");
+
+    /**
+     * The java.vm.specification.vendor System Property. Java Virtual
+     * Machine specification vendor.
+     *
+     * Defaults to null if the runtime does not have
+     * security access to read this property or the property does not exist.
+     * 
+     * @since Java 1.2
+     */
+    public static final String JAVA_VM_SPECIFICATION_VENDOR = getSystemProperty("java.vm.specification.vendor");
+
+    /**
+     * The java.vm.specification.version System Property. Java Virtual Machine
+     * specification version.
+     *
+     * Defaults to null if the runtime does not have
+     * security access to read this property or the property does not exist.
+     * 
+     * @since Java 1.2
+     */
+    public static final String JAVA_VM_SPECIFICATION_VERSION = getSystemProperty("java.vm.specification.version");
+
+    /**
+     * The java.vm.vendor System Property. Java Virtual Machine implementation
+     * vendor.
+     *
+     * Defaults to null if the runtime does not have
+     * security access to read this property or the property does not exist.
+     * 
+     * @since Java 1.2
+     */
+    public static final String JAVA_VM_VENDOR = getSystemProperty("java.vm.vendor");
+
+    /**
+     * The java.vm.version System Property. Java Virtual Machine
+     * implementation version.
+     *
+     * Defaults to null if the runtime does not have
+     * security access to read this property or the property does not exist.
+     * 
+     * @since Java 1.2
+     */
+    public static final String JAVA_VM_VERSION = getSystemProperty("java.vm.version");
+
+    /**
+     * The line.separator System Property. Line separator
+     * ("\n<" on UNIX).
+     *
+     * Defaults to null if the runtime does not have
+     * security access to read this property or the property does not exist.
+     * 
+     * @since Java 1.1
+     */
+    public static final String LINE_SEPARATOR = getSystemProperty("line.separator");
+
+    /**
+     * The os.arch System Property. Operating system architecture.
+     *
+     * Defaults to null if the runtime does not have
+     * security access to read this property or the property does not exist.
+     * 
+     * @since Java 1.1
+     */
+    public static final String OS_ARCH = getSystemProperty("os.arch");
+
+    /**
+     * The os.name System Property. Operating system name.
+     *
+     * Defaults to null if the runtime does not have
+     * security access to read this property or the property does not exist.
+     * 
+     * @since Java 1.1
+     */
+    public static final String OS_NAME = getSystemProperty("os.name");
+
+    /**
+     * The os.version System Property. Operating system version.
+     *
+     * Defaults to null if the runtime does not have
+     * security access to read this property or the property does not exist.
+     * 
+     * @since Java 1.1
+     */
+    public static final String OS_VERSION = getSystemProperty("os.version");
+
+    /**
+     * The path.separator System Property. Path separator
+     * (":" on UNIX).
+     *
+     * Defaults to null if the runtime does not have
+     * security access to read this property or the property does not exist.
+     * 
+     * @since Java 1.1
+     */
+    public static final String PATH_SEPARATOR = getSystemProperty("path.separator");
+
+    /**
+     * The user.country or user.region System Property.
+     * User's country code, such as GB. First in JDK version 1.2 as
+     * user.region. Renamed to user.country in 1.4
+     *
+     * Defaults to null if the runtime does not have
+     * security access to read this property or the property does not exist.
+     * 
+     * @since 2.0
+     * @since Java 1.2
+     */
+    public static final String USER_COUNTRY = 
+        (getSystemProperty("user.country") == null ?
+            getSystemProperty("user.region") : getSystemProperty("user.country"));
+
+    /**
+     * The user.dir System Property. User's current working
+     * directory.
+     *
+     * Defaults to null if the runtime does not have
+     * security access to read this property or the property does not exist.
+     * 
+     * @since Java 1.1
+     */
+    public static final String USER_DIR = getSystemProperty("user.dir");
+
+    /**
+     * The user.home System Property. User's home directory.
+     *
+     * Defaults to null if the runtime does not have
+     * security access to read this property or the property does not exist.
+     * 
+     * @since Java 1.1
+     */
+    public static final String USER_HOME = getSystemProperty("user.home");
+
+    /**
+     * The user.language System Property. User's language code,
+     * such as 'en'.
+     *
+     * Defaults to null if the runtime does not have
+     * security access to read this property or the property does not exist.
+     * 
+     * @since 2.0
+     * @since Java 1.2
+     */
+    public static final String USER_LANGUAGE = getSystemProperty("user.language");
+
+    /**
+     * The user.name System Property. User's account name.
+     *
+     * Defaults to null if the runtime does not have
+     * security access to read this property or the property does not exist.
+     * 
+     * @since Java 1.1
+     */
+    public static final String USER_NAME = getSystemProperty("user.name");
+
+    // Java version
+    //-----------------------------------------------------------------------
+    // These MUST be declared after those above as they depend on the
+    // values being set up
+    
+    /**
+     * Gets the Java version as a float.
+     *
+     * Example return values:
+     * 
+     *  1.2f for JDK 1.2
+     *  1.31f for JDK 1.3.1
+     * 
+     *
+     * The field will return zero if {@link #JAVA_VERSION} is null.
+     * 
+     * @since 2.0
+     */
+    public static final float JAVA_VERSION_FLOAT = getJavaVersionAsFloat();
+
+    /**
+     * Gets the Java version as an int.
+     *
+     * Example return values:
+     * 
+     *  120 for JDK 1.2
+     *  131 for JDK 1.3.1
+     * 
+     *
+     * The field will return zero if {@link #JAVA_VERSION} is null.
+     * 
+     * @since 2.0
+     */
+    public static final int JAVA_VERSION_INT = getJavaVersionAsInt();
+
+    // Java version checks
+    //-----------------------------------------------------------------------
+    // These MUST be declared after those above as they depend on the
+    // values being set up
+    
+    /**
+     * Is true if this is Java version 1.1 (also 1.1.x versions).
+     *
+     * The field will return false if {@link #JAVA_VERSION} is
+     * null.
+     */
+    public static final boolean IS_JAVA_1_1 = getJavaVersionMatches("1.1");
+
+    /**
+     * Is true if this is Java version 1.2 (also 1.2.x versions).
+     *
+     * The field will return false if {@link #JAVA_VERSION} is
+     * null.
+     */
+    public static final boolean IS_JAVA_1_2 = getJavaVersionMatches("1.2");
+
+    /**
+     * Is true if this is Java version 1.3 (also 1.3.x versions).
+     *
+     * The field will return false if {@link #JAVA_VERSION} is
+     * null.
+     */
+    public static final boolean IS_JAVA_1_3 = getJavaVersionMatches("1.3");
+
+    /**
+     * Is true if this is Java version 1.4 (also 1.4.x versions).
+     *
+     * The field will false false if {@link #JAVA_VERSION} is
+     * null.
+     */
+    public static final boolean IS_JAVA_1_4 = getJavaVersionMatches("1.4");
+
+    /**
+     * Is true if this is Java version 1.5 (also 1.5.x versions).
+     *
+     * The field will return false if {@link #JAVA_VERSION} is
+     * null.
+     */
+    public static final boolean IS_JAVA_1_5 = getJavaVersionMatches("1.5");
+
+    // Operating system checks
+    //-----------------------------------------------------------------------
+    // These MUST be declared after those above as they depend on the
+    // values being set up
+    // OS names from http://www.vamphq.com/os.html
+    // Selected ones included - please advise commons-dev@jakarta.apache.org
+    // if you want another added or a mistake corrected
+
+    /**
+     * Is true if this is AIX.
+     *
+     * The field will return false if OS_NAME is
+     * null.
+     * 
+     * @since 2.0
+     */
+    public static final boolean IS_OS_AIX = getOSMatches("AIX");
+
+    /**
+     * Is true if this is HP-UX.
+     *
+     * The field will return false if OS_NAME is
+     * null.
+     * 
+     * @since 2.0
+     */
+    public static final boolean IS_OS_HP_UX = getOSMatches("HP-UX");
+
+    /**
+     * Is true if this is Irix.
+     *
+     * The field will return false if OS_NAME is
+     * null.
+     * 
+     * @since 2.0
+     */
+    public static final boolean IS_OS_IRIX = getOSMatches("Irix");
+
+    /**
+     * Is true if this is Linux.
+     *
+     * The field will return false if OS_NAME is
+     * null.
+     * 
+     * @since 2.0
+     */
+    public static final boolean IS_OS_LINUX = getOSMatches("Linux") || getOSMatches("LINUX");
+
+    /**
+     * Is true if this is Mac.
+     *
+     * The field will return false if OS_NAME is
+     * null.
+     * 
+     * @since 2.0
+     */
+    public static final boolean IS_OS_MAC = getOSMatches("Mac");
+
+    /**
+     * Is true if this is Mac.
+     *
+     * The field will return false if OS_NAME is
+     * null.
+     * 
+     * @since 2.0
+     */
+    public static final boolean IS_OS_MAC_OSX = getOSMatches("Mac OS X");
+
+    /**
+     * Is true if this is OS/2.
+     *
+     * The field will return false if OS_NAME is
+     * null.
+     * 
+     * @since 2.0
+     */
+    public static final boolean IS_OS_OS2 = getOSMatches("OS/2");
+
+    /**
+     * Is true if this is Solaris.
+     *
+     * The field will return false if OS_NAME is
+     * null.
+     * 
+     * @since 2.0
+     */
+    public static final boolean IS_OS_SOLARIS = getOSMatches("Solaris");
+
+    /**
+     * Is true if this is SunOS.
+     *
+     * The field will return false if OS_NAME is
+     * null.
+     * 
+     * @since 2.0
+     */
+    public static final boolean IS_OS_SUN_OS = getOSMatches("SunOS");
+
+    /**
+     * Is true if this is Windows.
+     *
+     * The field will return false if OS_NAME is
+     * null.
+     * 
+     * @since 2.0
+     */
+    public static final boolean IS_OS_WINDOWS = getOSMatches("Windows");
+
+    /**
+     * Is true if this is Windows 2000.
+     *
+     * The field will return false if OS_NAME is
+     * null.
+     * 
+     * @since 2.0
+     */
+    public static final boolean IS_OS_WINDOWS_2000 = getOSMatches("Windows", "5.0");
+
+    /**
+     * Is true if this is Windows 95.
+     *
+     * The field will return false if OS_NAME is
+     * null.
+     * 
+     * @since 2.0
+     */
+    public static final boolean IS_OS_WINDOWS_95 = getOSMatches("Windows 9", "4.0");
+    // JDK 1.2 running on Windows98 returns 'Windows 95', hence the above
+
+    /**
+     * Is true if this is Windows 98.
+     *
+     * The field will return false if OS_NAME is
+     * null.
+     * 
+     * @since 2.0
+     */
+    public static final boolean IS_OS_WINDOWS_98 = getOSMatches("Windows 9", "4.1");
+    // JDK 1.2 running on Windows98 returns 'Windows 95', hence the above
+
+    /**
+     * Is true if this is Windows ME.
+     *
+     * The field will return false if OS_NAME is
+     * null.
+     * 
+     * @since 2.0
+     */
+    public static final boolean IS_OS_WINDOWS_ME = getOSMatches("Windows", "4.9");
+    // JDK 1.2 running on WindowsME may return 'Windows 95', hence the above
+
+    /**
+     * Is true if this is Windows NT.
+     *
+     * The field will return false if OS_NAME is
+     * null.
+     * 
+     * @since 2.0
+     */
+    public static final boolean IS_OS_WINDOWS_NT = getOSMatches("Windows NT");
+    // Windows 2000 returns 'Windows 2000' but may suffer from same JDK1.2 problem
+
+    /**
+     * Is true if this is Windows XP.
+     *
+     * The field will return false if OS_NAME is
+     * null.
+     * 
+     * @since 2.0
+     */
+    public static final boolean IS_OS_WINDOWS_XP = getOSMatches("Windows", "5.1");
+    // Windows XP returns 'Windows 2000' just for fun...
+
+    //-----------------------------------------------------------------------    
+    /**
+     * SystemUtils instances should NOT be constructed in standard
+     * programming. Instead, the class should be used as
+     * SystemUtils.FILE_SEPARATOR.
+     *
+     * This constructor is public to permit tools that require a JavaBean
+     * instance to operate.
+     */
+    public SystemUtils() {
+    }
+    
+    //-----------------------------------------------------------------------    
+    /**
+     * Gets the Java version number as a float.
+     *
+     * Example return values:
+     * 
+     *  1.2f for JDK 1.2
+     *  1.31f for JDK 1.3.1
+     * 
+     * 
+     * @return the version, for example 1.31f for JDK 1.3.1
+     * @deprecated Use {@link #JAVA_VERSION_FLOAT} instead.
+     *             Method will be removed in Commons Lang 3.0.
+     */
+    public static float getJavaVersion() {
+        return JAVA_VERSION_FLOAT;
+    }
+
+    /**
+     * Gets the Java version number as a float.
+     *
+     * Example return values:
+     * 
+     *  1.2f for JDK 1.2
+     *  1.31f for JDK 1.3.1
+     * 
+     * 
+     * Patch releases are not reported.
+     * Zero is returned if {@link #JAVA_VERSION} is null.
+     * 
+     * @return the version, for example 1.31f for JDK 1.3.1
+     */
+    private static float getJavaVersionAsFloat() {
+        if (JAVA_VERSION == null) {
+            return 0f;
+        }
+        String str = JAVA_VERSION.substring(0, 3);
+        if (JAVA_VERSION.length() >= 5) {
+            str = str + JAVA_VERSION.substring(4, 5);
+        }
+        return Float.parseFloat(str);
+    }
+    
+    /**
+     * Gets the Java version number as an int.
+     *
+     * Example return values:
+     * 
+     *  120 for JDK 1.2
+     *  131 for JDK 1.3.1
+     * 
+     * 
+     * Patch releases are not reported.
+     * Zero is returned if {@link #JAVA_VERSION} is null.
+     * 
+     * @return the version, for example 131 for JDK 1.3.1
+     */
+    private static int getJavaVersionAsInt() {
+        if (JAVA_VERSION == null) {
+            return 0;
+        }
+        String str = JAVA_VERSION.substring(0, 1);
+        str = str + JAVA_VERSION.substring(2, 3);
+        if (JAVA_VERSION.length() >= 5) {
+            str = str + JAVA_VERSION.substring(4, 5);
+        } else {
+            str = str + "0";
+        }
+        return Integer.parseInt(str);
+    }
+
+    /**
+     * Decides if the java version matches.
+     * 
+     * @param versionPrefix  the prefix for the java version
+     * @return true if matches, or false if not or can't determine
+     */
+    private static boolean getJavaVersionMatches(String versionPrefix) {
+        if (JAVA_VERSION == null) {
+            return false;
+        }
+        return JAVA_VERSION.startsWith(versionPrefix);
+    }    
+    
+    /**
+     * Decides if the operating system matches.
+     * 
+     * @param osNamePrefix  the prefix for the os name
+     * @return true if matches, or false if not or can't determine
+     */
+    private static boolean getOSMatches(String osNamePrefix) {
+        if (OS_NAME == null) {
+            return false;
+        }
+        return OS_NAME.startsWith(osNamePrefix);
+    }    
+
+    /**
+     * Decides if the operating system matches.
+     * 
+     * @param osNamePrefix  the prefix for the os name
+     * @param osVersionPrefix  the prefix for the version
+     * @return true if matches, or false if not or can't determine
+     */
+    private static boolean getOSMatches(String osNamePrefix, String osVersionPrefix) {
+        if (OS_NAME == null || OS_VERSION == null) {
+            return false;
+        }
+        return OS_NAME.startsWith(osNamePrefix) && OS_VERSION.startsWith(osVersionPrefix);
+    }    
+
+    //-----------------------------------------------------------------------
+    /**
+     * Gets a System property, defaulting to null if the property
+     * cannot be read.
+     *
+     * If a SecurityException is caught, the return
+     * value is null and a message is written to System.err.
+     * 
+     * @param property the system property name
+     * @return the system property value or null if a security problem occurs
+     */
+    private static String getSystemProperty(String property) {
+        try {
+            return System.getProperty(property);
+        } catch (SecurityException ex) {
+            // we are not allowed to look at this property
+            System.err.println(
+                "Caught a SecurityException reading the system property '" + property 
+                + "'; the SystemUtils property value will default to null."
+            );
+            return null;
+        }
+    }    
+    
+    /**
+     * Is the Java version at least the requested version.
+     *
+     * Example input:
+     * 
+     *  1.2f to test for JDK 1.2 
+     *  1.31f to test for JDK 1.3.1 
+     * 
+     * 
+     * @param requiredVersion  the required version, for example 1.31f
+     * @return true if the actual version is equal or greater
+     *  than the required version
+     */
+    public static boolean isJavaVersionAtLeast(float requiredVersion) {
+        return (JAVA_VERSION_FLOAT >= requiredVersion);
+    }
+    
+    /**
+     * Is the Java version at least the requested version.
+     *
+     * Example input:
+     * 
+     *  120 to test for JDK 1.2 or greater 
+     *  131 to test for JDK 1.3.1 or greater 
+     * 
+     * 
+     * @param requiredVersion  the required version, for example 131
+     * @return true if the actual version is equal or greater
+     *  than the required version
+     * @since 2.0
+     */
+    public static boolean isJavaVersionAtLeast(int requiredVersion) {
+        return (JAVA_VERSION_INT >= requiredVersion);
+    }
+    
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/UnhandledException.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/UnhandledException.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/UnhandledException.java	30 Aug 2012 16:24:42 -0000	1.1
@@ -0,0 +1,87 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang;
+
+import org.apache.commons.lang.exception.NestableRuntimeException;
+
+/**
+ * Thrown when it is impossible or undesirable to consume
+ * or throw a checked exception.
+ * 
+ * @author Matthew Hawthorne
+ * @since 2.0
+ * @version $Id: UnhandledException.java,v 1.1 2012/08/30 16:24:42 marcin Exp $
+ */
+public class UnhandledException extends NestableRuntimeException {
+
+    /**
+     * Constructs the exception using a cause.
+     * 
+     * @param cause  the underlying cause
+     */
+	public UnhandledException(Throwable cause) {
+		super(cause);
+	}
+
+    /**
+     * Constructs the exception using a message and cause.
+     * 
+     * @param message  the message to use
+     * @param cause  the underlying cause
+     */
+	public UnhandledException(String message, Throwable cause) {
+		super(message, cause);
+	}
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/Validate.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/Validate.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/Validate.java	30 Aug 2012 16:24:42 -0000	1.1
@@ -0,0 +1,524 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang;
+
+import java.util.Collection;
+import java.util.Iterator;
+import java.util.Map;
+
+/**
+ * Assists in validating arguments.
+ * 
+ * The class is based along the lines of JUnit. If an argument value is 
+ * deemed invalid, an IllegalArgumentException is thrown. For example:
+ * 
+ * 
+ * Validate.isTrue( i > 0, "The value must be greater than zero: ", i);
+ * Validate.notNull( surname, "The surname must not be null");
+ * 
+ *
+ * @author Ola Berg
+ * @author Stephen Colebourne
+ * @author Gary Gregory
+ * @since 2.0
+ * @version $Id: Validate.java,v 1.1 2012/08/30 16:24:42 marcin Exp $
+ */
+public class Validate {
+    
+    /**
+     * Constructor. This class should not normally be instantiated.
+     */
+    public Validate() {
+    }
+    
+    // isTrue
+    //---------------------------------------------------------------------------------
+
+    /**
+     * Validate an argument, throwing IllegalArgumentException
+     * if the test result is false.
+     * 
+     * This is used when validating according to an arbitrary boolean expression,
+     * such as validating a primitive number or using your own custom validation 
+     * expression.
+     *
+     * 
+     * Validate.isTrue( myObject.isOk(), "The object is not OK: ", myObject);
+     * 
+     *
+     * For performance reasons, the object is passed as a separate parameter and
+     * appended to the message string only in the case of an error.
+     * 
+     * @param expression  a boolean expression
+     * @param message  the exception message you would like to see if the
+     *  expression is false
+     * @param value  the value to append to the message in case of error
+     * @throws IllegalArgumentException if expression is false
+     */
+    public static void isTrue(boolean expression, String message, Object value) {
+        if (expression == false) {
+            throw new IllegalArgumentException(message + value);
+        }
+    }
+
+    /**
+     * Validate an argument, throwing IllegalArgumentException
+     * if the test result is false.
+     * 
+     * This is used when validating according to an arbitrary boolean expression,
+     * such as validating a primitive number or using your own custom validation 
+     * expression.
+     *
+     * 
+     * Validate.isTrue( i > 0, "The value must be greater than zero: ", i);
+     * 
+     *
+     * For performance reasons, the object is passed as a separate parameter and
+     * appended to the message string only in the case of an error.
+     * 
+     * @param expression  a boolean expression
+     * @param message  the exception message you would like to see if the expression is false
+     * @param value  the value to append to the message in case of error
+     * @throws IllegalArgumentException if expression is false
+     */
+    public static void isTrue(boolean expression, String message, long value) {
+        if (expression == false) {
+            throw new IllegalArgumentException(message + value);
+        }
+    }
+
+    /**
+     * Validate an argument, throwing IllegalArgumentException
+     * if the test result is false.
+     * 
+     * This is used when validating according to an arbitrary boolean expression,
+     * such as validating a primitive number or using your own custom validation 
+     * expression.
+     *
+     * 
+     * Validate.isTrue( d > 0.0, "The value must be greater than zero: ", d);
+     * 
+     *
+     * For performance reasons, the object is passed as a separate parameter and
+     * appended to the message string only in the case of an error.
+     * 
+     * @param expression  a boolean expression
+     * @param message  the exception message you would like to see if the expression
+     *  is false
+     * @param value  the value to append to the message in case of error
+     * @throws IllegalArgumentException if expression is false
+     */
+    public static void isTrue(boolean expression, String message, double value) {
+        if (expression == false) {
+            throw new IllegalArgumentException(message + value);
+        }
+    }
+
+    /**
+     * Validate an argument, throwing IllegalArgumentException
+     * if the test result is false.
+     * 
+     * This is used when validating according to an arbitrary boolean expression,
+     * such as validating a primitive number or using your own custom validation 
+     * expression.
+     *
+     * 
+     * Validate.isTrue( (i > 0), "The value must be greater than zero");
+     * Validate.isTrue( myObject.isOk(), "The object is not OK");
+     * 
+     *
+     * For performance reasons, the message string should not involve a string append,
+     * instead use the {@link #isTrue(boolean, String, Object)} method.
+     * 
+     * @param expression  a boolean expression
+     * @param message  the exception message you would like to see if the expression
+     *  is false
+     * @throws IllegalArgumentException if expression is false
+     */
+    public static void isTrue(boolean expression, String message) {
+        if (expression == false) {
+            throw new IllegalArgumentException(message);
+        }
+    }
+
+    /**
+     * Validate an argument, throwing IllegalArgumentException
+     * if the test result is false.
+     * 
+     * This is used when validating according to an arbitrary boolean expression,
+     * such as validating a primitive number or using your own custom validation 
+     * expression.
+     *
+     * 
+     * Validate.isTrue( i > 0 );
+     * Validate.isTrue( myObject.isOk() );
+     * 
+     *
+     * The message in the exception is 'The validated expression is false'.
+     * 
+     * @param expression  a boolean expression
+     * @throws IllegalArgumentException if expression is false
+     */
+    public static void isTrue(boolean expression) {
+        if (expression == false) {
+            throw new IllegalArgumentException("The validated expression is false");
+        }
+    }
+
+    // notNull
+    //---------------------------------------------------------------------------------
+
+    /**
+     * Validate an argument, throwing IllegalArgumentException
+     * if the argument is null.
+     *
+     * 
+     * Validate.notNull(myObject, "The object must not be null");
+     * 
+     * 
+     * @param object  the object to check is not null
+     * @param message  the exception message you would like to see
+     *  if the object is null
+     * @throws IllegalArgumentException if the object is null
+     */
+    public static void notNull(Object object, String message) {
+        if (object == null) {
+            throw new IllegalArgumentException(message);
+        }
+    }
+
+    /**
+     * Validate an argument, throwing IllegalArgumentException
+     * if the argument is null.
+     *
+     * 
+     * Validate.notNull(myObject);
+     * 
+     *
+     * The message in the exception is 'The validated object is null'.
+     * 
+     * @param object  the object to check is not null
+     * @throws IllegalArgumentException if the object is null
+     */
+    public static void notNull(Object object) {
+        if (object == null) {
+            throw new IllegalArgumentException("The validated object is null");
+        }
+    }
+
+    // notEmpty array
+    //---------------------------------------------------------------------------------
+
+    /**
+     * Validate an argument, throwing IllegalArgumentException
+     * if the argument array is empty (null or no elements).
+     *
+     * 
+     * Validate.notEmpty(myArray, "The array must not be empty");
+     * 
+     * 
+     * @param array  the array to check is not empty
+     * @param message  the exception message you would like to see if the array is empty
+     * @throws IllegalArgumentException if the array is empty
+     */
+    public static void notEmpty(Object[] array, String message) {
+        if (array == null || array.length == 0) {
+            throw new IllegalArgumentException(message);
+        }
+    }
+
+    /**
+     * Validate an argument, throwing IllegalArgumentException
+     * if the argument array is empty (null or no elements).
+     *
+     * 
+     * Validate.notEmpty(myArray);
+     * 
+     *
+     * The message in the exception is 'The validated array is empty'.
+     * 
+     * @param array  the array to check is not empty
+     * @throws IllegalArgumentException if the array is empty
+     */
+    public static void notEmpty(Object[] array) {
+        if (array == null || array.length == 0) {
+            throw new IllegalArgumentException("The validated array is empty");
+        }
+    }
+
+    // notEmpty collection
+    //---------------------------------------------------------------------------------
+
+    /**
+     * 
Validate an argument, throwing IllegalArgumentException
+     * if the argument Collection is empty (null or no elements).
+     *
+     * 
+     * Validate.notEmpty(myCollection, "The collection must not be empty");
+     * 
+     * 
+     * @param collection  the collection to check is not empty
+     * @param message  the exception message you would like to see if the collection is empty
+     * @throws IllegalArgumentException if the collection is empty
+     */
+    public static void notEmpty(Collection collection, String message) {
+        if (collection == null || collection.size() == 0) {
+            throw new IllegalArgumentException(message);
+        }
+    }
+
+    /**
+     * Validate an argument, throwing IllegalArgumentException
+     * if the argument Collection is empty (null or no elements).
+     *
+     * 
+     * Validate.notEmpty(myCollection);
+     * 
+     *
+     * The message in the exception is 'The validated collection is empty'.
+     * 
+     * @param collection  the collection to check is not empty
+     * @throws IllegalArgumentException if the collection is empty
+     */
+    public static void notEmpty(Collection collection) {
+        if (collection == null || collection.size() == 0) {
+            throw new IllegalArgumentException("The validated collection is empty");
+        }
+    }
+
+    // notEmpty map
+    //---------------------------------------------------------------------------------
+
+    /**
+     * Validate an argument, throwing IllegalArgumentException
+     * if the argument Map is empty (null or no elements).
+     *
+     * 
+     * Validate.notEmpty(myMap, "The collection must not be empty");
+     * 
+     * 
+     * @param map  the map to check is not empty
+     * @param message  the exception message you would like to see if the map is empty
+     * @throws IllegalArgumentException if the map is empty
+     */
+    public static void notEmpty(Map map, String message) {
+        if (map == null || map.size() == 0) {
+            throw new IllegalArgumentException(message);
+        }
+    }
+
+    /**
+     * Validate an argument, throwing IllegalArgumentException
+     * if the argument Map is empty (null or no elements).
+     *
+     * 
+     * Validate.notEmpty(myMap);
+     * 
+     *
+     * The message in the exception is 'The validated map is empty'.
+     * 
+     * @param map  the map to check is not empty
+     * @throws IllegalArgumentException if the map is empty
+     */
+    public static void notEmpty(Map map) {
+        if (map == null || map.size() == 0) {
+            throw new IllegalArgumentException("The validated map is empty");
+        }
+    }
+
+    // notEmpty string
+    //---------------------------------------------------------------------------------
+
+    /**
+     * Validate an argument, throwing IllegalArgumentException
+     * if the argument String is empty (null or zero length).
+     *
+     * 
+     * Validate.notEmpty(myString, "The string must not be empty");
+     * 
+     * 
+     * @param string  the string to check is not empty
+     * @param message  the exception message you would like to see if the string is empty
+     * @throws IllegalArgumentException if the string is empty
+     */
+    public static void notEmpty(String string, String message) {
+        if (string == null || string.length() == 0) {
+            throw new IllegalArgumentException(message);
+        }
+    }
+
+    /**
+     * Validate an argument, throwing IllegalArgumentException
+     * if the argument String is empty (null or zero length).
+     *
+     * 
+     * Validate.notEmpty(myString);
+     * 
+     *
+     * The message in the exception is 'The validated string is empty'.
+     * 
+     * @param string  the string to check is not empty
+     * @throws IllegalArgumentException if the string is empty
+     */
+    public static void notEmpty(String string) {
+        if (string == null || string.length() == 0) {
+            throw new IllegalArgumentException("The validated string is empty");
+        }
+    }
+
+    // notNullElements array
+    //---------------------------------------------------------------------------------
+
+    /**
+     * Validate an argument, throwing IllegalArgumentException
+     * if the argument array has null elements or is
+     * null.
+     *
+     * 
+     * Validate.notEmpty(myArray, "The array must not contain null elements");
+     * 
+     * 
+     * @param array  the array to check
+     * @param message  the exception message if the array has
+     *  null elements
+     * @throws IllegalArgumentException if the array has null
+     *  elements or is null
+     */
+    public static void noNullElements(Object[] array, String message) {
+        Validate.notNull(array);
+        for (int i = 0; i < array.length; i++) {
+            if (array[i] == null) {
+                throw new IllegalArgumentException(message);
+            }
+        }
+    }
+
+    /**
+     * Validate an argument, throwing IllegalArgumentException
+     * if the argument array has null elements or is
+     * null.
+     *
+     * 
+     * Validate.notEmpty(myArray);
+     * 
+     *
+     * The message in the exception is 'The validated array contains null element at index: '.
+     * 
+     * @param array  the array to check
+     * @throws IllegalArgumentException if the array has null
+     *  elements or is null
+     */
+    public static void noNullElements(Object[] array) {
+        Validate.notNull(array);
+        for (int i = 0; i < array.length; i++) {
+            if (array[i] == null) {
+                throw new IllegalArgumentException("The validated array contains null element at index: " + i);
+            }
+        }
+    }
+
+    // notNullElements collection
+    //---------------------------------------------------------------------------------
+
+    /**
+     * Validate an argument, throwing IllegalArgumentException
+     * if the argument collection has null elements or is
+     * null.
+     *
+     * 
+     * Validate.notEmpty(myCollection, "The collection must not contain null elements");
+     * 
+     * 
+     * @param collection  the collection to check
+     * @param message  the exception message if the array has
+     *  null elements
+     * @throws IllegalArgumentException if the collection has
+     *  null elements or is null
+     */
+    public static void noNullElements(Collection collection, String message) {
+        Validate.notNull(collection);
+        int i = 0;
+        for (Iterator it = collection.iterator(); it.hasNext(); i++) {
+            if (it.next() == null) {
+                throw new IllegalArgumentException(message);
+            }
+        }
+    }
+
+    /**
+     * Validate an argument, throwing IllegalArgumentException
+     * if the argument collection has null elements or is
+     * null.
+     *
+     * 
+     * Validate.notEmpty(myCollection);
+     * 
+     *
+     * The message in the exception is 'The validated collection contains null element at index: '.
+     * 
+     * @param collection  the collection to check
+     * @throws IllegalArgumentException if the collection has
+     *  null elements or is null
+     */
+    public static void noNullElements(Collection collection) {
+        Validate.notNull(collection);
+        int i = 0;
+        for (Iterator it = collection.iterator(); it.hasNext(); i++) {
+            if (it.next() == null) {
+                throw new IllegalArgumentException("The validated collection contains null element at index: " + i);
+            }
+        }
+    }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/WordUtils.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/WordUtils.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/WordUtils.java	30 Aug 2012 16:24:42 -0000	1.1
@@ -0,0 +1,433 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang;
+
+/**
+ * Operations on Strings that contain words.
+ * 
+ * This class tries to handle null input gracefully.
+ * An exception will not be thrown for a null input.
+ * Each method documents its behaviour in more detail.
+ * 
+ * @author Apache Jakarta Velocity
+ * @author Henri Yandell
+ * @author Stephen Colebourne
+ * @author Henning P. Schmiedehausen
+ * @author Gary Gregory
+ * @since 2.0
+ * @version $Id: WordUtils.java,v 1.1 2012/08/30 16:24:42 marcin Exp $
+ */
+public class WordUtils {
+
+    /**
+     * WordWrapUtils instances should NOT be constructed in
+     * standard programming. Instead, the class should be used as
+     * WordWrapUtils.wrap("foo bar", 20);.
+     *
+     * This constructor is public to permit tools that require a JavaBean
+     * instance to operate.
+     */
+    public WordUtils() {
+    }
+
+    // Wrapping
+    //--------------------------------------------------------------------------
+//    /**
+//     * Wraps a block of text to a specified line length using '\n' as
+//     * a newline.
+//     *
+//     * This method takes a block of text, which might have long lines in it
+//     * and wraps the long lines based on the supplied lineLength parameter.
+//     * 
+//     * If a single word is longer than the line length (eg. a URL), it will
+//     * not be broken, and will display beyond the expected width.
+//     * 
+//     * If there are tabs in inString, you are going to get results that are
+//     * a bit strange. Tabs are a single character but are displayed as 4 or 8
+//     * spaces. Remove the tabs.
+//     *
+//     * @param str  text which is in need of word-wrapping, may be null
+//     * @param lineLength  the column to wrap the words at
+//     * @return the text with all the long lines word-wrapped
+//     *  null if null string input
+//     */
+//    public static String wrapText(String str, int lineLength) {
+//        return wrap(str, null, lineLength);
+//    }
+    
+//    /**
+//     * Wraps a block of text to a specified line length.
+//     *
+//     * This method takes a block of text, which might have long lines in it
+//     * and wraps the long lines based on the supplied lineLength parameter.
+//     * 
+//     * If a single word is longer than the wrapColumn (eg. a URL), it will
+//     * not be broken, and will display beyond the expected width.
+//     * 
+//     * If there are tabs in inString, you are going to get results that are
+//     * a bit strange. Tabs are a single character but are displayed as 4 or 8
+//     * spaces. Remove the tabs.
+//     *
+//     * @param str  text which is in need of word-wrapping, may be null
+//     * @param newLineChars  the characters that define a newline, null treated as \n
+//     * @param lineLength  the column to wrap the words at
+//     * @return the text with all the long lines word-wrapped
+//     *  null if null string input
+//     */
+//    public static String wrapText(String str, String newLineChars, int lineLength) {
+//        if (str == null) {
+//            return null;
+//        }
+//        if (newLineChars == null) {
+//            newLineChars = "\n";
+//        }
+//        StringTokenizer lineTokenizer = new StringTokenizer(str, newLineChars, true);
+//        StringBuffer stringBuffer = new StringBuffer();
+//
+//        while (lineTokenizer.hasMoreTokens()) {
+//            try {
+//                String nextLine = lineTokenizer.nextToken();
+//
+//                if (nextLine.length() > lineLength) {
+//                    // This line is long enough to be wrapped.
+//                    nextLine = wrapLine(nextLine, null, lineLength, false);
+//                }
+//
+//                stringBuffer.append(nextLine);
+//
+//            } catch (NoSuchElementException nsee) {
+//                // thrown by nextToken(), but I don't know why it would
+//                break;
+//            }
+//        }
+//
+//        return (stringBuffer.toString());
+//    }
+
+    // Wrapping
+    //-----------------------------------------------------------------------
+    /**
+     * Wraps a single line of text, identifying words by ' '.
+     * 
+     * New lines will be separated by the system property line separator.
+     * Very long words, such as URLs will not be wrapped.
+     * 
+     * Leading spaces on a new line are stripped.
+     * Trailing spaces are not stripped.
+     *
+     * 
+     * WordUtils.wrap(null, *) = null
+     * WordUtils.wrap("", *) = ""
+     * 
+     *
+     * @param str  the String to be word wrapped, may be null
+     * @param wrapLength  the column to wrap the words at, less than 1 is treated as 1
+     * @return a line with newlines inserted, null if null input
+     */
+    public static String wrap(String str, int wrapLength) {
+        return wrap(str, wrapLength, null, false);
+    }
+    
+    /**
+     * Wraps a single line of text, identifying words by ' '.
+     * 
+     * Leading spaces on a new line are stripped.
+     * Trailing spaces are not stripped.
+     * 
+     * 
+     * WordUtils.wrap(null, *, *, *) = null
+     * WordUtils.wrap("", *, *, *) = ""
+     * 
+     *
+     * @param str  the String to be word wrapped, may be null
+     * @param wrapLength  the column to wrap the words at, less than 1 is treated as 1
+     * @param newLineStr  the string to insert for a new line, 
+     *  null uses the system property line separator
+     * @param wrapLongWords  true if long words (such as URLs) should be wrapped
+     * @return a line with newlines inserted, null if null input
+     */
+    public static String wrap(String str, int wrapLength, String newLineStr, boolean wrapLongWords) {
+        if (str == null) {
+            return null;
+        }
+        if (newLineStr == null) {
+            newLineStr = SystemUtils.LINE_SEPARATOR;
+        }
+        if (wrapLength < 1) {
+            wrapLength = 1;
+        }
+        int inputLineLength = str.length();
+        int offset = 0;
+        StringBuffer wrappedLine = new StringBuffer(inputLineLength + 32);
+        
+        while ((inputLineLength - offset) > wrapLength) {
+            if (str.charAt(offset) == ' ') {
+                offset++;
+                continue;
+            }
+            int spaceToWrapAt = str.lastIndexOf(' ', wrapLength + offset);
+
+            if (spaceToWrapAt >= offset) {
+                // normal case
+                wrappedLine.append(str.substring(offset, spaceToWrapAt));
+                wrappedLine.append(newLineStr);
+                offset = spaceToWrapAt + 1;
+                
+            } else {
+                // really long word or URL
+                if (wrapLongWords) {
+                    // wrap really long word one line at a time
+                    wrappedLine.append(str.substring(offset, wrapLength + offset));
+                    wrappedLine.append(newLineStr);
+                    offset += wrapLength;
+                } else {
+                    // do not wrap really long word, just extend beyond limit
+                    spaceToWrapAt = str.indexOf(' ', wrapLength + offset);
+                    if (spaceToWrapAt >= 0) {
+                        wrappedLine.append(str.substring(offset, spaceToWrapAt));
+                        wrappedLine.append(newLineStr);
+                        offset = spaceToWrapAt + 1;
+                    } else {
+                        wrappedLine.append(str.substring(offset));
+                        offset = inputLineLength;
+                    }
+                }
+            }
+        }
+
+        // Whatever is left in line is short enough to just pass through
+        wrappedLine.append(str.substring(offset));
+
+        return wrappedLine.toString();
+    }
+
+    // Capitalizing
+    //-----------------------------------------------------------------------
+    /**
+     * Capitalizes all the whitespace separated words in a String.
+     * Only the first letter of each word is changed. To change all letters to
+     * the capitalized case, use {@link #capitalizeFully(String)}.
+     *
+     * Whitespace is defined by {@link Character#isWhitespace(char)}.
+     * A null input String returns null.
+     * Capitalization uses the unicode title case, normally equivalent to
+     * upper case.
+     *
+     * 
+     * WordUtils.capitalize(null)        = null
+     * WordUtils.capitalize("")          = ""
+     * WordUtils.capitalize("i am FINE") = "I Am FINE"
+     * 
+     * 
+     * @param str  the String to capitalize, may be null
+     * @return capitalized String, null if null String input
+     * @see #uncapitalize(String)
+     * @see #capitalizeFully(String)
+     */
+    public static String capitalize(String str) {
+        int strLen;
+        if (str == null || (strLen = str.length()) == 0) {
+            return str;
+        }
+        StringBuffer buffer = new StringBuffer(strLen);
+        boolean whitespace = true;
+        for (int i = 0; i < strLen; i++) {
+            char ch = str.charAt(i);
+            if (Character.isWhitespace(ch)) {
+                buffer.append(ch);
+                whitespace = true;
+            } else if (whitespace) {
+                buffer.append(Character.toTitleCase(ch));
+                whitespace = false;
+            } else {
+                buffer.append(ch);
+            }
+        }
+        return buffer.toString();
+    }
+
+    /**
+     * Capitalizes all the whitespace separated words in a String.
+     * All letters are changed, so the resulting string will be fully changed.
+     *
+     * Whitespace is defined by {@link Character#isWhitespace(char)}.
+     * A null input String returns null.
+     * Capitalization uses the unicode title case, normally equivalent to
+     * upper case.
+     *
+     * 
+     * WordUtils.capitalize(null)        = null
+     * WordUtils.capitalize("")          = ""
+     * WordUtils.capitalize("i am FINE") = "I Am Fine"
+     * 
+     * 
+     * @param str  the String to capitalize, may be null
+     * @return capitalized String, null if null String input
+     */
+    public static String capitalizeFully(String str) {
+        int strLen;
+        if (str == null || (strLen = str.length()) == 0) {
+            return str;
+        }
+        StringBuffer buffer = new StringBuffer(strLen);
+        boolean whitespace = true;
+        for (int i = 0; i < strLen; i++) {
+            char ch = str.charAt(i);
+            if (Character.isWhitespace(ch)) {
+                buffer.append(ch);
+                whitespace = true;
+            } else if (whitespace) {
+                buffer.append(Character.toTitleCase(ch));
+                whitespace = false;
+            } else {
+                buffer.append(Character.toLowerCase(ch));
+            }
+        }
+        return buffer.toString();
+    }
+
+    /**
+     * Uncapitalizes all the whitespace separated words in a String.
+     * Only the first letter of each word is changed.
+     *
+     * Whitespace is defined by {@link Character#isWhitespace(char)}.
+     * A null input String returns null.
+     *
+     * 
+     * WordUtils.uncapitalize(null)        = null
+     * WordUtils.uncapitalize("")          = ""
+     * WordUtils.uncapitalize("I Am FINE") = "i am fINE"
+     * 
+     * 
+     * @param str  the String to uncapitalize, may be null
+     * @return uncapitalized String, null if null String input
+     * @see #capitalize(String)
+     */
+    public static String uncapitalize(String str) {
+        int strLen;
+        if (str == null || (strLen = str.length()) == 0) {
+            return str;
+        }
+        StringBuffer buffer = new StringBuffer(strLen);
+        boolean whitespace = true;
+        for (int i = 0; i < strLen; i++) {
+            char ch = str.charAt(i);
+            if (Character.isWhitespace(ch)) {
+                buffer.append(ch);
+                whitespace = true;
+            } else if (whitespace) {
+                buffer.append(Character.toLowerCase(ch));
+                whitespace = false;
+            } else {
+                buffer.append(ch);
+            }
+        }
+        return buffer.toString();
+    }
+
+    /**
+     * Swaps the case of a String using a word based algorithm.
+     * 
+     * 
+     *  - Upper case character converts to Lower case
 
+     *  - Title case character converts to Lower case
 
+     *  - Lower case character after Whitespace or at start converts to Title case
 
+     *  - Other Lower case character converts to Upper case
 
+     * 
+     * 
+     * Whitespace is defined by {@link Character#isWhitespace(char)}.
+     * A null input String returns null.
+     * 
+     * 
+     * StringUtils.swapCase(null)                 = null
+     * StringUtils.swapCase("")                   = ""
+     * StringUtils.swapCase("The dog has a BONE") = "tHE DOG HAS A bone"
+     * 
+     * 
+     * @param str  the String to swap case, may be null
+     * @return the changed String, null if null String input
+     */
+    public static String swapCase(String str) {
+        int strLen;
+        if (str == null || (strLen = str.length()) == 0) {
+            return str;
+        }
+        StringBuffer buffer = new StringBuffer(strLen);
+
+        boolean whitespace = true;
+        char ch = 0;
+        char tmp = 0;
+
+        for (int i = 0; i < strLen; i++) {
+            ch = str.charAt(i);
+            if (Character.isUpperCase(ch)) {
+                tmp = Character.toLowerCase(ch);
+            } else if (Character.isTitleCase(ch)) {
+                tmp = Character.toLowerCase(ch);
+            } else if (Character.isLowerCase(ch)) {
+                if (whitespace) {
+                    tmp = Character.toTitleCase(ch);
+                } else {
+                    tmp = Character.toUpperCase(ch);
+                }
+            } else {
+                tmp = ch;
+            }
+            buffer.append(tmp);
+            whitespace = Character.isWhitespace(ch);
+        }
+        return buffer.toString();
+    }
+    
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/overview.html
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/overview.html,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/overview.html	30 Aug 2012 16:24:42 -0000	1.1
@@ -0,0 +1,7 @@
+
+
+
+This document is the API specification for the Apache Jakarta Commons Lang Library, version 2.0.
+
+
+
\ No newline at end of file
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/package.html
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/package.html,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/package.html	30 Aug 2012 16:24:42 -0000	1.1
@@ -0,0 +1,7 @@
+
+
+Provides highly reusable static utility methods, chiefly concerned 
+with adding value to java.lang and other standard core classes.
+@since 1.0
+
+
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/CompareToBuilder.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/builder/CompareToBuilder.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/CompareToBuilder.java	30 Aug 2012 16:24:43 -0000	1.1
@@ -0,0 +1,966 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang.builder;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.Comparator;
+
+import org.apache.commons.lang.math.NumberUtils;
+
+/** 
+ * Assists in implementing {@link java.lang.Comparable#compareTo(Object)} methods.
+ *
+ * It is consistent with equals(Object) and
+ * hashcode() built with {@link EqualsBuilder} and
+ * {@link HashCodeBuilder}.
+ *
+ * Two Objects that compare equal using equals(Object) should normally
+ * also compare equal using compareTo(Object).
+ *
+ * All relevant fields should be included in the calculation of the
+ * comparison. Derived fields may be ignored. The same fields, in the same
+ * order, should be used in both compareTo(Object) and
+ * equals(Object).
+ *
+ * To use this class write code as follows:
+ *
+ * 
+ * public class MyClass {
+ *   String field1;
+ *   int field2;
+ *   boolean field3;
+ *
+ *   ...
+ *
+ *   public int compareTo(Object o) {
+ *     MyClass myClass = (MyClass) o;
+ *     return new CompareToBuilder()
+ *       .appendSuper(super.compareTo(o)
+ *       .append(this.field1, myClass.field1)
+ *       .append(this.field2, myClass.field2)
+ *       .append(this.field3, myClass.field3)
+ *       .toComparison();
+ *   }
+ * }
+ * 
+ *
+ * Alternatively, there is a method {@link #reflectionCompare reflectionCompare} that uses
+ * reflection to determine the fields to append. Because fields can be private,
+ * reflectionCompare uses {@link java.lang.reflect.AccessibleObject#setAccessible(boolean)} to
+ * bypass normal access control checks. This will fail under a security manager,
+ * unless the appropriate permissions are set up correctly. It is also
+ * slower than appending explicitly.
+ *
+ * A typical implementation of compareTo(Object) using
+ * reflectionCompare looks like:
+
+ * 
+ * public int compareTo(Object o) {
+ *   return CompareToBuilder.reflectionCompare(this, o);
+ * }
+ * 
+ *
+ * @see java.lang.Comparable
+ * @see java.lang.Object#equals(Object)
+ * @see java.lang.Object#hashCode()
+ * @see EqualsBuilder
+ * @see HashCodeBuilder
+ * @author Steve Downey
+ * @author Stephen Colebourne
+ * @author Gary Gregory
+ * @author Pete Gieser
+ * @since 1.0
+ * @version $Id: CompareToBuilder.java,v 1.1 2012/08/30 16:24:43 marcin Exp $
+ */
+public class CompareToBuilder {
+    
+    /**
+     * Current state of the comparison as appended fields are checked.
+     */
+    private int comparison;
+
+    /**
+     * Constructor for CompareToBuilder.
+     *
+     * Starts off assuming that the objects are equal. Multiple calls are 
+     * then made to the various append methods, followed by a call to 
+     * {@link #toComparison} to get the result.
+     */
+    public CompareToBuilder() {
+        super();
+        comparison = 0;
+    }
+
+    //-----------------------------------------------------------------------
+    /** 
+     * Compares two Objects via reflection.
+     *
+     * Fields can be private, thus AccessibleObject.setAccessible
+     * is used to bypass normal access control checks. This will fail under a 
+     * security manager unless the appropriate permissions are set.
+     *
+     * 
+     * - Static fields will not be compared
 
+     * - Transient members will be not be compared, as they are likely derived
+     *     fields
 
+     * - Superclass fields will be compared
 
+     * 
+     *
+     * If both lhs and rhs are null,
+     * they are considered equal.
+     *
+     * @param lhs  left-hand object
+     * @param rhs  right-hand object
+     * @return a negative integer, zero, or a positive integer as lhs
+     *  is less than, equal to, or greater than rhs
+     * @throws NullPointerException  if either (but not both) parameters are
+     *  null
+     * @throws ClassCastException  if rhs is not assignment-compatible
+     *  with lhs
+     */
+    public static int reflectionCompare(Object lhs, Object rhs) {
+        return reflectionCompare(lhs, rhs, false, null);
+    }
+
+    /**
+     * Compares two Objects via reflection.
+     *
+     * Fields can be private, thus AccessibleObject.setAccessible
+     * is used to bypass normal access control checks. This will fail under a 
+     * security manager unless the appropriate permissions are set.
+     *
+     * 
+     * - Static fields will not be compared
 
+     * - If 
compareTransients is true,
+     *     compares transient members.  Otherwise ignores them, as they
+     *     are likely derived fields. 
+     * - Superclass fields will be compared
 
+     * 
+     *
+     * If both lhs and rhs are null,
+     * they are considered equal.
+     *
+     * @param lhs  left-hand object
+     * @param rhs  right-hand object
+     * @param compareTransients  whether to compare transient fields
+     * @return a negative integer, zero, or a positive integer as lhs
+     *  is less than, equal to, or greater than rhs
+     * @throws NullPointerException  if either lhs or rhs
+     *  (but not both) is null
+     * @throws ClassCastException  if rhs is not assignment-compatible
+     *  with lhs
+     */
+    public static int reflectionCompare(Object lhs, Object rhs, boolean compareTransients) {
+        return reflectionCompare(lhs, rhs, compareTransients, null);
+    }
+
+    /**
+     * Compares two Objects via reflection.
+     *
+     * Fields can be private, thus AccessibleObject.setAccessible
+     * is used to bypass normal access control checks. This will fail under a 
+     * security manager unless the appropriate permissions are set.
+     *
+     * 
+     * - Static fields will not be compared
 
+     * - If the 
compareTransients is true,
+     *     compares transient members.  Otherwise ignores them, as they
+     *     are likely derived fields. 
+     * - Compares superclass fields up to and including 
reflectUpToClass.
+     *     If reflectUpToClass is null, compares all superclass fields. 
+     * 
+     *
+     * If both lhs and rhs are null,
+     * they are considered equal.
+     *
+     * @param lhs  left-hand object
+     * @param rhs  right-hand object
+     * @param compareTransients  whether to compare transient fields
+     * @param reflectUpToClass  last superclass for which fields are compared
+     * @return a negative integer, zero, or a positive integer as lhs
+     *  is less than, equal to, or greater than rhs
+     * @throws NullPointerException  if either lhs or rhs
+     *  (but not both) is null
+     * @throws ClassCastException  if rhs is not assignment-compatible
+     *  with lhs
+     * @since 2.0
+     */
+    public static int reflectionCompare(Object lhs, Object rhs, boolean compareTransients, Class reflectUpToClass) {
+        if (lhs == rhs) {
+            return 0;
+        }
+        if (lhs == null || rhs == null) {
+            throw new NullPointerException();
+        }
+        Class lhsClazz = lhs.getClass();
+        if (!lhsClazz.isInstance(rhs)) {
+            throw new ClassCastException();
+        }
+        CompareToBuilder compareToBuilder = new CompareToBuilder();
+        reflectionAppend(lhs, rhs, lhsClazz, compareToBuilder, compareTransients);
+        while (lhsClazz.getSuperclass() != null && lhsClazz != reflectUpToClass) {
+            lhsClazz = lhsClazz.getSuperclass();
+            reflectionAppend(lhs, rhs, lhsClazz, compareToBuilder, compareTransients);
+        }
+        return compareToBuilder.toComparison();
+    }
+
+    /**
+     * Appends to builder the comparison of lhs
+     * to rhs using the fields defined in clazz.
+     * 
+     * @param lhs  left-hand object
+     * @param rhs  right-hand object
+     * @param clazz  Class that defines fields to be compared
+     * @param builder  CompareToBuilder to append to
+     * @param useTransients  whether to compare transient fields
+     */
+    private static void reflectionAppend(
+        Object lhs,
+        Object rhs,
+        Class clazz,
+        CompareToBuilder builder,
+        boolean useTransients) {
+        
+        Field[] fields = clazz.getDeclaredFields();
+        AccessibleObject.setAccessible(fields, true);
+        for (int i = 0; i < fields.length && builder.comparison == 0; i++) {
+            Field f = fields[i];
+            if ((f.getName().indexOf('$') == -1)
+                && (useTransients || !Modifier.isTransient(f.getModifiers()))
+                && (!Modifier.isStatic(f.getModifiers()))) {
+                try {
+                    builder.append(f.get(lhs), f.get(rhs));
+                } catch (IllegalAccessException e) {
+                    // This can't happen. Would get a Security exception instead.
+                    // Throw a runtime exception in case the impossible happens.
+                    throw new InternalError("Unexpected IllegalAccessException");
+                }
+            }
+        }
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Appends to the builder the compareTo(Object)
+     * result of the superclass.
+     *
+     * @param superCompareTo  result of calling super.compareTo(Object)
+     * @return this - used to chain append calls
+     * @since 2.0
+     */
+    public CompareToBuilder appendSuper(int superCompareTo) {
+        if (comparison != 0) {
+            return this;
+        }
+        comparison = superCompareTo;
+        return this;
+    }
+    
+    //-----------------------------------------------------------------------
+    /**
+     * Appends to the builder the comparison of
+     * two Objects.
+     *
+     * 
+     * - Check if 
lhs == rhs 
+     * - Check if either 
lhs or rhs is null,
+     *     a null object is less than a non-null object 
+     * - Check the object contents
 
+     * 
+     * 
+     * lhs must either be an array or implement {@link Comparable}.
+     *
+     * @param lhs  left-hand object
+     * @param rhs  right-hand object
+     * @return this - used to chain append calls
+     * @throws ClassCastException  if rhs is not assignment-compatible
+     *  with lhs
+     */
+    public CompareToBuilder append(Object lhs, Object rhs) {
+        return append(lhs, rhs, null);
+    }
+
+    /**
+     * Appends to the builder the comparison of
+     * two Objects.
+     *
+     * 
+     * - Check if 
lhs == rhs 
+     * - Check if either 
lhs or rhs is null,
+     *     a null object is less than a non-null object 
+     * - Check the object contents
 
+     * 
+     *
+     * If lhs is an array, array comparison methods will be used.
+     * Otherwise comparator will be used to compare the objects.
+     * If comparator is null, lhs must
+     * implement {@link Comparable} instead.
+     *
+     * @param lhs  left-hand object
+     * @param rhs  right-hand object
+     * @param comparator  Comparator used to compare the objects,
+     *  null means treat lhs as Comparable
+     * @return this - used to chain append calls
+     * @throws ClassCastException  if rhs is not assignment-compatible
+     *  with lhs
+     * @since 2.0
+     */
+    public CompareToBuilder append(Object lhs, Object rhs, Comparator comparator) {
+        if (comparison != 0) {
+            return this;
+        }
+        if (lhs == rhs) {
+            return this;
+        }
+        if (lhs == null) {
+            comparison = -1;
+            return this;
+        }
+        if (rhs == null) {
+            comparison = +1;
+            return this;
+        }
+        if (lhs.getClass().isArray()) {
+            // switch on type of array, to dispatch to the correct handler
+            // handles multi dimensional arrays
+            // throws a ClassCastException if rhs is not the correct array type
+            if (lhs instanceof long[]) {
+                append((long[]) lhs, (long[]) rhs);
+            } else if (lhs instanceof int[]) {
+                append((int[]) lhs, (int[]) rhs);
+            } else if (lhs instanceof short[]) {
+                append((short[]) lhs, (short[]) rhs);
+            } else if (lhs instanceof char[]) {
+                append((char[]) lhs, (char[]) rhs);
+            } else if (lhs instanceof byte[]) {
+                append((byte[]) lhs, (byte[]) rhs);
+            } else if (lhs instanceof double[]) {
+                append((double[]) lhs, (double[]) rhs);
+            } else if (lhs instanceof float[]) {
+                append((float[]) lhs, (float[]) rhs);
+            } else if (lhs instanceof boolean[]) {
+                append((boolean[]) lhs, (boolean[]) rhs);
+            } else {
+                // not an array of primitives
+                // throws a ClassCastException if rhs is not an array
+                append((Object[]) lhs, (Object[]) rhs, comparator);
+            }
+        } else {
+            // the simple case, not an array, just test the element
+            if (comparator == null) {
+                comparison = ((Comparable) lhs).compareTo(rhs);
+            } else {
+                comparison = comparator.compare(lhs, rhs);
+            }
+        }
+        return this;
+    }
+
+    //-------------------------------------------------------------------------
+    /**
+     * Appends to the builder the comparison of
+     * two longs.
+     *
+     * @param lhs  left-hand value
+     * @param rhs  right-hand value
+     * @return this - used to chain append calls
+     */
+    public CompareToBuilder append(long lhs, long rhs) {
+        if (comparison != 0) {
+            return this;
+        }
+        comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0));
+        return this;
+    }
+
+    /**
+     * Appends to the builder the comparison of
+     * two ints.
+     *
+     * @param lhs  left-hand value
+     * @param rhs  right-hand value
+     * @return this - used to chain append calls
+     */
+    public CompareToBuilder append(int lhs, int rhs) {
+        if (comparison != 0) {
+            return this;
+        }
+        comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0));
+        return this;
+    }
+
+    /**
+     * Appends to the builder the comparison of
+     * two shorts.
+     * 
+     * @param lhs  left-hand value
+     * @param rhs  right-hand value
+     * @return this - used to chain append calls
+     */
+    public CompareToBuilder append(short lhs, short rhs) {
+        if (comparison != 0) {
+            return this;
+        }
+        comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0));
+        return this;
+    }
+
+    /**
+     * Appends to the builder the comparison of
+     * two chars.
+     *
+     * @param lhs  left-hand value
+     * @param rhs  right-hand value
+     * @return this - used to chain append calls
+     */
+    public CompareToBuilder append(char lhs, char rhs) {
+        if (comparison != 0) {
+            return this;
+        }
+        comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0));
+        return this;
+    }
+
+    /**
+     * Appends to the builder the comparison of
+     * two bytes.
+     * 
+     * @param lhs  left-hand value
+     * @param rhs  right-hand value
+     * @return this - used to chain append calls
+     */
+    public CompareToBuilder append(byte lhs, byte rhs) {
+        if (comparison != 0) {
+            return this;
+        }
+        comparison = ((lhs < rhs) ? -1 : ((lhs > rhs) ? 1 : 0));
+        return this;
+    }
+
+    /**
+     * Appends to the builder the comparison of
+     * two doubles.
+     *
+     * This handles NaNs, Infinties, and -0.0.
+     *
+     * It is compatible with the hash code generated by
+     * HashCodeBuilder.
+     *
+     * @param lhs  left-hand value
+     * @param rhs  right-hand value
+     * @return this - used to chain append calls
+     */
+    public CompareToBuilder append(double lhs, double rhs) {
+        if (comparison != 0) {
+            return this;
+        }
+        comparison = NumberUtils.compare(lhs, rhs);
+        return this;
+    }
+
+    /**
+     * Appends to the builder the comparison of
+     * two floats.
+     *
+     * This handles NaNs, Infinties, and -0.0.
+     *
+     * It is compatible with the hash code generated by
+     * HashCodeBuilder.
+     *
+     * @param lhs  left-hand value
+     * @param rhs  right-hand value
+     * @return this - used to chain append calls
+     */
+    public CompareToBuilder append(float lhs, float rhs) {
+        if (comparison != 0) {
+            return this;
+        }
+        comparison = NumberUtils.compare(lhs, rhs);
+        return this;
+    }
+
+    /**
+     * Appends to the builder the comparison of
+     * two booleanss.
+     *
+     * @param lhs  left-hand value
+     * @param rhs  right-hand value
+     * @return this - used to chain append calls
+      */
+    public CompareToBuilder append(boolean lhs, boolean rhs) {
+        if (comparison != 0) {
+            return this;
+        }
+        if (lhs == rhs) {
+            return this;
+        }
+        if (lhs == false) {
+            comparison = -1;
+        } else {
+            comparison = +1;
+        }
+        return this;
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Appends to the builder the deep comparison of
+     * two Object arrays.
+     *
+     * 
+     *  - Check if arrays are the same using 
== 
+     *  - Check if for 
null, null is less than non-null 
+     *  - Check array length, a short length array is less than a long length array
 
+     *  - Check array contents element by element using {@link #append(Object, Object, Comparator)}
 
+     * 
+     *
+     * This method will also will be called for the top level of multi-dimensional,
+     * ragged, and multi-typed arrays.
+     *
+     * @param lhs  left-hand array
+     * @param rhs  right-hand array
+     * @return this - used to chain append calls
+     * @throws ClassCastException  if rhs is not assignment-compatible
+     *  with lhs
+     */
+    public CompareToBuilder append(Object[] lhs, Object[] rhs) {
+        return append(lhs, rhs, null);
+    }
+    
+    /**
+     * Appends to the builder the deep comparison of
+     * two Object arrays.
+     *
+     * 
+     *  - Check if arrays are the same using 
== 
+     *  - Check if for 
null, null is less than non-null 
+     *  - Check array length, a short length array is less than a long length array
 
+     *  - Check array contents element by element using {@link #append(Object, Object, Comparator)}
 
+     * 
+     *
+     * This method will also will be called for the top level of multi-dimensional,
+     * ragged, and multi-typed arrays.
+     *
+     * @param lhs  left-hand array
+     * @param rhs  right-hand array
+     * @param comparator  Comparator to use to compare the array elements,
+     *  null means to treat lhs elements as Comparable.
+     * @return this - used to chain append calls
+     * @throws ClassCastException  if rhs is not assignment-compatible
+     *  with lhs
+     * @since 2.0
+     */
+    public CompareToBuilder append(Object[] lhs, Object[] rhs, Comparator comparator) {
+        if (comparison != 0) {
+            return this;
+        }
+        if (lhs == rhs) {
+            return this;
+        }
+        if (lhs == null) {
+            comparison = -1;
+            return this;
+        }
+        if (rhs == null) {
+            comparison = +1;
+            return this;
+        }
+        if (lhs.length != rhs.length) {
+            comparison = (lhs.length < rhs.length) ? -1 : +1;
+            return this;
+        }
+        for (int i = 0; i < lhs.length && comparison == 0; i++) {
+            append(lhs[i], rhs[i], comparator);
+        }
+        return this;
+    }
+
+    /**
+     * Appends to the builder the deep comparison of
+     * two long arrays.
+     *
+     * 
+     *  - Check if arrays are the same using 
== 
+     *  - Check if for 
null, null is less than non-null 
+     *  - Check array length, a shorter length array is less than a longer length array
 
+     *  - Check array contents element by element using {@link #append(long, long)}
 
+     * 
+     *
+     * @param lhs  left-hand array
+     * @param rhs  right-hand array
+     * @return this - used to chain append calls
+     */
+    public CompareToBuilder append(long[] lhs, long[] rhs) {
+        if (comparison != 0) {
+            return this;
+        }
+        if (lhs == rhs) {
+            return this;
+        }
+        if (lhs == null) {
+            comparison = -1;
+            return this;
+        }
+        if (rhs == null) {
+            comparison = +1;
+            return this;
+        }
+        if (lhs.length != rhs.length) {
+            comparison = (lhs.length < rhs.length) ? -1 : +1;
+            return this;
+        }
+        for (int i = 0; i < lhs.length && comparison == 0; i++) {
+            append(lhs[i], rhs[i]);
+        }
+        return this;
+    }
+
+    /**
+     * Appends to the builder the deep comparison of
+     * two int arrays.
+     *
+     * 
+     *  - Check if arrays are the same using 
== 
+     *  - Check if for 
null, null is less than non-null 
+     *  - Check array length, a shorter length array is less than a longer length array
 
+     *  - Check array contents element by element using {@link #append(int, int)}
 
+     * 
+     *
+     * @param lhs  left-hand array
+     * @param rhs  right-hand array
+     * @return this - used to chain append calls
+     */
+    public CompareToBuilder append(int[] lhs, int[] rhs) {
+        if (comparison != 0) {
+            return this;
+        }
+        if (lhs == rhs) {
+            return this;
+        }
+        if (lhs == null) {
+            comparison = -1;
+            return this;
+        }
+        if (rhs == null) {
+            comparison = +1;
+            return this;
+        }
+        if (lhs.length != rhs.length) {
+            comparison = (lhs.length < rhs.length) ? -1 : +1;
+            return this;
+        }
+        for (int i = 0; i < lhs.length && comparison == 0; i++) {
+            append(lhs[i], rhs[i]);
+        }
+        return this;
+    }
+
+    /**
+     * Appends to the builder the deep comparison of
+     * two short arrays.
+     *
+     * 
+     *  - Check if arrays are the same using 
== 
+     *  - Check if for 
null, null is less than non-null 
+     *  - Check array length, a shorter length array is less than a longer length array
 
+     *  - Check array contents element by element using {@link #append(short, short)}
 
+     * 
+     *
+     * @param lhs  left-hand array
+     * @param rhs  right-hand array
+     * @return this - used to chain append calls
+     */
+    public CompareToBuilder append(short[] lhs, short[] rhs) {
+        if (comparison != 0) {
+            return this;
+        }
+        if (lhs == rhs) {
+            return this;
+        }
+        if (lhs == null) {
+            comparison = -1;
+            return this;
+        }
+        if (rhs == null) {
+            comparison = +1;
+            return this;
+        }
+        if (lhs.length != rhs.length) {
+            comparison = (lhs.length < rhs.length) ? -1 : +1;
+            return this;
+        }
+        for (int i = 0; i < lhs.length && comparison == 0; i++) {
+            append(lhs[i], rhs[i]);
+        }
+        return this;
+    }
+
+    /**
+     * Appends to the builder the deep comparison of
+     * two char arrays.
+     *
+     * 
+     *  - Check if arrays are the same using 
== 
+     *  - Check if for 
null, null is less than non-null 
+     *  - Check array length, a shorter length array is less than a longer length array
 
+     *  - Check array contents element by element using {@link #append(char, char)}
 
+     * 
+     *
+     * @param lhs  left-hand array
+     * @param rhs  right-hand array
+     * @return this - used to chain append calls
+     */
+    public CompareToBuilder append(char[] lhs, char[] rhs) {
+        if (comparison != 0) {
+            return this;
+        }
+        if (lhs == rhs) {
+            return this;
+        }
+        if (lhs == null) {
+            comparison = -1;
+            return this;
+        }
+        if (rhs == null) {
+            comparison = +1;
+            return this;
+        }
+        if (lhs.length != rhs.length) {
+            comparison = (lhs.length < rhs.length) ? -1 : +1;
+            return this;
+        }
+        for (int i = 0; i < lhs.length && comparison == 0; i++) {
+            append(lhs[i], rhs[i]);
+        }
+        return this;
+    }
+
+    /**
+     * Appends to the builder the deep comparison of
+     * two byte arrays.
+     *
+     * 
+     *  - Check if arrays are the same using 
== 
+     *  - Check if for 
null, null is less than non-null 
+     *  - Check array length, a shorter length array is less than a longer length array
 
+     *  - Check array contents element by element using {@link #append(byte, byte)}
 
+     * 
+     *
+     * @param lhs  left-hand array
+     * @param rhs  right-hand array
+     * @return this - used to chain append calls
+     */
+    public CompareToBuilder append(byte[] lhs, byte[] rhs) {
+        if (comparison != 0) {
+            return this;
+        }
+        if (lhs == rhs) {
+            return this;
+        }
+        if (lhs == null) {
+            comparison = -1;
+            return this;
+        }
+        if (rhs == null) {
+            comparison = +1;
+            return this;
+        }
+        if (lhs.length != rhs.length) {
+            comparison = (lhs.length < rhs.length) ? -1 : +1;
+            return this;
+        }
+        for (int i = 0; i < lhs.length && comparison == 0; i++) {
+            append(lhs[i], rhs[i]);
+        }
+        return this;
+    }
+
+    /**
+     * Appends to the builder the deep comparison of
+     * two double arrays.
+     *
+     * 
+     *  - Check if arrays are the same using 
== 
+     *  - Check if for 
null, null is less than non-null 
+     *  - Check array length, a shorter length array is less than a longer length array
 
+     *  - Check array contents element by element using {@link #append(double, double)}
 
+     * 
+     *
+     * @param lhs  left-hand array
+     * @param rhs  right-hand array
+     * @return this - used to chain append calls
+     */
+    public CompareToBuilder append(double[] lhs, double[] rhs) {
+        if (comparison != 0) {
+            return this;
+        }
+        if (lhs == rhs) {
+            return this;
+        }
+        if (lhs == null) {
+            comparison = -1;
+            return this;
+        }
+        if (rhs == null) {
+            comparison = +1;
+            return this;
+        }
+        if (lhs.length != rhs.length) {
+            comparison = (lhs.length < rhs.length) ? -1 : +1;
+            return this;
+        }
+        for (int i = 0; i < lhs.length && comparison == 0; i++) {
+            append(lhs[i], rhs[i]);
+        }
+        return this;
+    }
+
+    /**
+     * Appends to the builder the deep comparison of
+     * two float arrays.
+     *
+     * 
+     *  - Check if arrays are the same using 
== 
+     *  - Check if for 
null, null is less than non-null 
+     *  - Check array length, a shorter length array is less than a longer length array
 
+     *  - Check array contents element by element using {@link #append(float, float)}
 
+     * 
+     *
+     * @param lhs  left-hand array
+     * @param rhs  right-hand array
+     * @return this - used to chain append calls
+     */
+    public CompareToBuilder append(float[] lhs, float[] rhs) {
+        if (comparison != 0) {
+            return this;
+        }
+        if (lhs == rhs) {
+            return this;
+        }
+        if (lhs == null) {
+            comparison = -1;
+            return this;
+        }
+        if (rhs == null) {
+            comparison = +1;
+            return this;
+        }
+        if (lhs.length != rhs.length) {
+            comparison = (lhs.length < rhs.length) ? -1 : +1;
+            return this;
+        }
+        for (int i = 0; i < lhs.length && comparison == 0; i++) {
+            append(lhs[i], rhs[i]);
+        }
+        return this;
+    }
+
+    /**
+     * Appends to the builder the deep comparison of
+     * two boolean arrays.
+     *
+     * 
+     *  - Check if arrays are the same using 
== 
+     *  - Check if for 
null, null is less than non-null 
+     *  - Check array length, a shorter length array is less than a longer length array
 
+     *  - Check array contents element by element using {@link #append(boolean, boolean)}
 
+     * 
+     *
+     * @param lhs  left-hand array
+     * @param rhs  right-hand array
+     * @return this - used to chain append calls
+     */
+    public CompareToBuilder append(boolean[] lhs, boolean[] rhs) {
+        if (comparison != 0) {
+            return this;
+        }
+        if (lhs == rhs) {
+            return this;
+        }
+        if (lhs == null) {
+            comparison = -1;
+            return this;
+        }
+        if (rhs == null) {
+            comparison = +1;
+            return this;
+        }
+        if (lhs.length != rhs.length) {
+            comparison = (lhs.length < rhs.length) ? -1 : +1;
+            return this;
+        }
+        for (int i = 0; i < lhs.length && comparison == 0; i++) {
+            append(lhs[i], rhs[i]);
+        }
+        return this;
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Returns a negative integer, a positive integer, or zero as
+     * the builder has judged the "left-hand" side
+     * as less than, greater than, or equal to the "right-hand"
+     * side.
+     * 
+     * @return final comparison result
+     */
+    public int toComparison() {
+        return comparison;
+    }
+
+}
+
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/EqualsBuilder.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/builder/EqualsBuilder.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/EqualsBuilder.java	30 Aug 2012 16:24:43 -0000	1.1
@@ -0,0 +1,781 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang.builder;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+
+/**
+ * Assists in implementing {@link Object#equals(Object)} methods.
+ *
+ *  This class provides methods to build a good equals method for any
+ * class. It follows rules laid out in
+ * Effective Java
+ * , by Joshua Bloch. In particular the rule for comparing doubles,
+ * floats, and arrays can be tricky. Also, making sure that
+ * equals() and hashCode() are consistent can be
+ * difficult.
+ *
+ * Two Objects that compare as equals must generate the same hash code,
+ * but two Objects with the same hash code do not have to be equal.
+ *
+ * All relevant fields should be included in the calculation of equals.
+ * Derived fields may be ignored. In particular, any field used in
+ * generating a hash code must be used in the equals method, and vice
+ * versa.
+ *
+ * Typical use for the code is as follows:
+ * 
+ * public boolean equals(Object o) {
+ *   if ( !(o instanceof MyClass) ) {
+ *    return false;
+ *   }
+ *  MyClass rhs = (MyClass) o;
+ *  return new EqualsBuilder()
+ *                 .appendSuper(super.equals(o))
+ *                 .append(field1, rhs.field1)
+ *                 .append(field2, rhs.field2)
+ *                 .append(field3, rhs.field3)
+ *                 .isEquals();
+ *  }
+ * 
+ *
+ *  Alternatively, there is a method that uses reflection to determine
+ * the fields to test. Because these fields are usually private, the method,
+ * reflectionEquals, uses AccessibleObject.setAccessible to
+ * change the visibility of the fields. This will fail under a security
+ * manager, unless the appropriate permissions are set up correctly. It is
+ * also slower than testing explicitly.
+ *
+ *  A typical invocation for this method would look like:
+ * 
+ * public boolean equals(Object o) {
+ *   return EqualsBuilder.reflectionEquals(this, o);
+ * }
+ * 
+ *
+ * @author Steve Downey
+ * @author Stephen Colebourne
+ * @author Gary Gregory
+ * @author Pete Gieser
+ * @since 1.0
+ * @version $Id: EqualsBuilder.java,v 1.1 2012/08/30 16:24:43 marcin Exp $
+ */
+public class EqualsBuilder {
+    /**
+     * If the fields tested are equals.
+     */
+    private boolean isEquals;
+
+    /**
+     * Constructor for EqualsBuilder.
+     *
+     * Starts off assuming that equals is true.
+     * @see java.lang.Object#equals
+     */
+    public EqualsBuilder() {
+        super();
+        isEquals = true;
+    }
+
+    //-------------------------------------------------------------------------
+
+    /**
+     * This method uses reflection to determine if the two Objects
+     * are equal.
+     *
+     * It uses AccessibleObject.setAccessible to gain access to private
+     * fields. This means that it will throw a security exception if run under
+     * a security manager, if the permissions are not set up correctly. It is also
+     * not as efficient as testing explicitly.
+     *
+     * Transient members will be not be tested, as they are likely derived
+     * fields, and not part of the value of the Object.
+     *
+     * Static fields will not be tested. Superclass fields will be included.
+     *
+     * @param lhs  this object
+     * @param rhs  the other object
+     * @return true if the two Objects have tested equals.
+     */
+    public static boolean reflectionEquals(Object lhs, Object rhs) {
+        return reflectionEquals(lhs, rhs, false, null);
+    }
+
+    /**
+     * This method uses reflection to determine if the two Objects
+     * are equal.
+     *
+     * It uses AccessibleObject.setAccessible to gain access to private
+     * fields. This means that it will throw a security exception if run under
+     * a security manager, if the permissions are not set up correctly. It is also
+     * not as efficient as testing explicitly.
+     *
+     * If the TestTransients parameter is set to true, transient
+     * members will be tested, otherwise they are ignored, as they are likely
+     * derived fields, and not part of the value of the Object.
+     *
+     * Static fields will not be tested. Superclass fields will be included.
+     *
+     * @param lhs  this object
+     * @param rhs  the other object
+     * @param testTransients  whether to include transient fields
+     * @return true if the two Objects have tested equals.
+     */
+    public static boolean reflectionEquals(Object lhs, Object rhs, boolean testTransients) {
+        return reflectionEquals(lhs, rhs, testTransients, null);
+    }
+
+    /**
+     * This method uses reflection to determine if the two Objects
+     * are equal.
+     *
+     * It uses AccessibleObject.setAccessible to gain access to private
+     * fields. This means that it will throw a security exception if run under
+     * a security manager, if the permissions are not set up correctly. It is also
+     * not as efficient as testing explicitly.
+     *
+     * If the testTransients parameter is set to true, transient
+     * members will be tested, otherwise they are ignored, as they are likely
+     * derived fields, and not part of the value of the Object.
+     *
+     * Static fields will not be included. Superclass fields will be appended
+     * up to and including the specified superclass. A null superclass is treated
+     * as java.lang.Object.
+     *
+     * @param lhs  this object
+     * @param rhs  the other object
+     * @param testTransients  whether to include transient fields
+     * @param reflectUpToClass  the superclass to reflect up to (inclusive),
+     *  may be null
+     * @return true if the two Objects have tested equals.
+     * @since 2.0
+     */
+    public static boolean reflectionEquals(Object lhs, Object rhs, boolean testTransients, Class reflectUpToClass) {
+        if (lhs == rhs) {
+            return true;
+        }
+        if (lhs == null || rhs == null) {
+            return false;
+        }
+        // Find the leaf class since there may be transients in the leaf 
+        // class or in classes between the leaf and root.
+        // If we are not testing transients or a subclass has no ivars, 
+        // then a subclass can test equals to a superclass.
+        Class lhsClass = lhs.getClass();
+        Class rhsClass = rhs.getClass();
+        Class testClass;
+        if (lhsClass.isInstance(rhs)) {
+            testClass = lhsClass;
+            if (!rhsClass.isInstance(lhs)) {
+                // rhsClass is a subclass of lhsClass
+                testClass = rhsClass;
+            }
+        } else if (rhsClass.isInstance(lhs)) {
+            testClass = rhsClass;
+            if (!lhsClass.isInstance(rhs)) {
+                // lhsClass is a subclass of rhsClass
+                testClass = lhsClass;
+            }
+        } else {
+            // The two classes are not related.
+            return false;
+        }
+        EqualsBuilder equalsBuilder = new EqualsBuilder();
+        try {
+            reflectionAppend(lhs, rhs, testClass, equalsBuilder, testTransients);
+            while (testClass.getSuperclass() != null && testClass != reflectUpToClass) {
+                testClass = testClass.getSuperclass();
+                reflectionAppend(lhs, rhs, testClass, equalsBuilder, testTransients);
+            }
+        } catch (IllegalArgumentException e) {
+            // In this case, we tried to test a subclass vs. a superclass and
+            // the subclass has ivars or the ivars are transient and 
+            // we are testing transients.
+            // If a subclass has ivars that we are trying to test them, we get an
+            // exception and we know that the objects are not equal.
+            return false;
+        }
+        return equalsBuilder.isEquals();
+    }
+
+    /**
+     * Appends the fields and values defined by the given object of the
+     * given Class.
+     * 
+     * @param lhs  the left hand object
+     * @param rhs  the right hand object
+     * @param clazz  the class to append details of
+     * @param builder  the builder to append to
+     * @param useTransients  whether to test transient fields
+     */
+    private static void reflectionAppend(
+        Object lhs,
+        Object rhs,
+        Class clazz,
+        EqualsBuilder builder,
+        boolean useTransients) {
+        Field[] fields = clazz.getDeclaredFields();
+        AccessibleObject.setAccessible(fields, true);
+        for (int i = 0; i < fields.length && builder.isEquals; i++) {
+            Field f = fields[i];
+            if ((f.getName().indexOf('$') == -1)
+                && (useTransients || !Modifier.isTransient(f.getModifiers()))
+                && (!Modifier.isStatic(f.getModifiers()))) {
+                try {
+                    builder.append(f.get(lhs), f.get(rhs));
+                } catch (IllegalAccessException e) {
+                    //this can't happen. Would get a Security exception instead
+                    //throw a runtime exception in case the impossible happens.
+                    throw new InternalError("Unexpected IllegalAccessException");
+                }
+            }
+        }
+    }
+
+    //-------------------------------------------------------------------------
+
+    /**
+     * Adds the result of super.equals() to this builder.
+     *
+     * @param superEquals  the result of calling super.equals()
+     * @return EqualsBuilder - used to chain calls.
+     * @since 2.0
+     */
+    public EqualsBuilder appendSuper(boolean superEquals) {
+        if (isEquals == false) {
+            return this;
+        }
+        isEquals = superEquals;
+        return this;
+    }
+
+    //-------------------------------------------------------------------------
+
+    /**
+     * Test if two Objects are equal using their
+     * equals method.
+     *
+     * @param lhs  the left hand object
+     * @param rhs  the right hand object
+     * @return EqualsBuilder - used to chain calls.
+     */
+    public EqualsBuilder append(Object lhs, Object rhs) {
+        if (isEquals == false) {
+            return this;
+        }
+        if (lhs == rhs) {
+            return this;
+        }
+        if (lhs == null || rhs == null) {
+            isEquals = false;
+            return this;
+        }
+        Class lhsClass = lhs.getClass();
+        if (!lhsClass.isArray()) {
+            //the simple case, not an array, just test the element
+            isEquals = lhs.equals(rhs);
+        } else {
+            //'Switch' on type of array, to dispatch to the correct handler
+            // This handles multi dimensional arrays
+            if (lhs instanceof long[]) {
+                append((long[]) lhs, (long[]) rhs);
+            } else if (lhs instanceof int[]) {
+                append((int[]) lhs, (int[]) rhs);
+            } else if (lhs instanceof short[]) {
+                append((short[]) lhs, (short[]) rhs);
+            } else if (lhs instanceof char[]) {
+                append((char[]) lhs, (char[]) rhs);
+            } else if (lhs instanceof byte[]) {
+                append((byte[]) lhs, (byte[]) rhs);
+            } else if (lhs instanceof double[]) {
+                append((double[]) lhs, (double[]) rhs);
+            } else if (lhs instanceof float[]) {
+                append((float[]) lhs, (float[]) rhs);
+            } else if (lhs instanceof boolean[]) {
+                append((boolean[]) lhs, (boolean[]) rhs);
+            } else {
+                // Not an array of primitives
+                append((Object[]) lhs, (Object[]) rhs);
+            }
+        }
+        return this;
+    }
+
+    /**
+     * Test if two longs are equal.
+     *
+     * @param lhs  the left hand long
+     * @param rhs  the right hand long
+     * @return EqualsBuilder - used to chain calls.
+     */
+    public EqualsBuilder append(long lhs, long rhs) {
+        if (isEquals == false) {
+            return this;
+        }
+        isEquals = (lhs == rhs);
+        return this;
+    }
+
+    /**
+     * Test if two ints are equal.
+     *
+     * @param lhs  the left hand int
+     * @param rhs  the right hand int
+     * @return EqualsBuilder - used to chain calls.
+     */
+    public EqualsBuilder append(int lhs, int rhs) {
+        if (isEquals == false) {
+            return this;
+        }
+        isEquals = (lhs == rhs);
+        return this;
+    }
+
+    /**
+     * Test if two shorts are equal.
+     *
+     * @param lhs  the left hand short
+     * @param rhs  the right hand short
+     * @return EqualsBuilder - used to chain calls.
+     */
+    public EqualsBuilder append(short lhs, short rhs) {
+        if (isEquals == false) {
+            return this;
+        }
+        isEquals = (lhs == rhs);
+        return this;
+    }
+
+    /**
+     * Test if two chars are equal.
+     *
+     * @param lhs  the left hand char
+     * @param rhs  the right hand char
+     * @return EqualsBuilder - used to chain calls.
+     */
+    public EqualsBuilder append(char lhs, char rhs) {
+        if (isEquals == false) {
+            return this;
+        }
+        isEquals = (lhs == rhs);
+        return this;
+    }
+
+    /**
+     * Test if two bytes are equal.
+     *
+     * @param lhs  the left hand byte
+     * @param rhs  the right hand byte
+     * @return EqualsBuilder - used to chain calls.
+     */
+    public EqualsBuilder append(byte lhs, byte rhs) {
+        if (isEquals == false) {
+            return this;
+        }
+        isEquals = (lhs == rhs);
+        return this;
+    }
+
+    /**
+     * Test if two doubles are equal by testing that the
+     * pattern of bits returned by doubleToLong are equal.
+     *
+     * This handles NaNs, Infinties, and -0.0.
+     *
+     * It is compatible with the hash code generated by
+     * HashCodeBuilder.
+     *
+     * @param lhs  the left hand double
+     * @param rhs  the right hand double
+     * @return EqualsBuilder - used to chain calls.
+     */
+    public EqualsBuilder append(double lhs, double rhs) {
+        if (isEquals == false) {
+            return this;
+        }
+        return append(Double.doubleToLongBits(lhs), Double.doubleToLongBits(rhs));
+    }
+
+    /**
+     * Test if two floats are equal byt testing that the
+     * pattern of bits returned by doubleToLong are equal.
+     *
+     * This handles NaNs, Infinties, and -0.0.
+     *
+     * It is compatible with the hash code generated by
+     * HashCodeBuilder.
+     *
+     * @param lhs  the left hand float
+     * @param rhs  the right hand float
+     * @return EqualsBuilder - used to chain calls.
+     */
+    public EqualsBuilder append(float lhs, float rhs) {
+        if (isEquals == false) {
+            return this;
+        }
+        return append(Float.floatToIntBits(lhs), Float.floatToIntBits(rhs));
+    }
+
+    /**
+     * Test if two booleanss are equal.
+     *
+     * @param lhs  the left hand boolean
+     * @param rhs  the right hand boolean
+     * @return EqualsBuilder - used to chain calls.
+      */
+    public EqualsBuilder append(boolean lhs, boolean rhs) {
+        if (isEquals == false) {
+            return this;
+        }
+        isEquals = (lhs == rhs);
+        return this;
+    }
+
+    /**
+     * Performs a deep comparison of two Object arrays.
+     *
+     * This also will be called for the top level of
+     * multi-dimensional, ragged, and multi-typed arrays.
+     *
+     * @param lhs  the left hand Object[]
+     * @param rhs  the right hand Object[]
+     * @return EqualsBuilder - used to chain calls.
+     */
+    public EqualsBuilder append(Object[] lhs, Object[] rhs) {
+        if (isEquals == false) {
+            return this;
+        }
+        if (lhs == rhs) {
+            return this;
+        }
+        if (lhs == null || rhs == null) {
+            isEquals = false;
+            return this;
+        }
+        if (lhs.length != rhs.length) {
+            isEquals = false;
+            return this;
+        }
+        for (int i = 0; i < lhs.length && isEquals; ++i) {
+            Class lhsClass = lhs[i].getClass();
+            if (!lhsClass.isInstance(rhs[i])) {
+                isEquals = false; //If the types don't match, not equal
+                break;
+            }
+            append(lhs[i], rhs[i]);
+        }
+        return this;
+    }
+
+    /**
+     * Deep comparison of array of long. Length and all
+     * values are compared.
+     *
+     * The method {@link #append(long, long)} is used.
+     *
+     * @param lhs  the left hand long[]
+     * @param rhs  the right hand long[]
+     * @return EqualsBuilder - used to chain calls.
+     */
+    public EqualsBuilder append(long[] lhs, long[] rhs) {
+        if (isEquals == false) {
+            return this;
+        }
+        if (lhs == rhs) {
+            return this;
+        }
+        if (lhs == null || rhs == null) {
+            isEquals = false;
+            return this;
+        }
+        if (lhs.length != rhs.length) {
+            isEquals = false;
+            return this;
+        }
+        for (int i = 0; i < lhs.length && isEquals; ++i) {
+            append(lhs[i], rhs[i]);
+        }
+        return this;
+    }
+
+    /**
+     * Deep comparison of array of int. Length and all
+     * values are compared.
+     *
+     * The method {@link #append(int, int)} is used.
+     *
+     * @param lhs  the left hand int[]
+     * @param rhs  the right hand int[]
+     * @return EqualsBuilder - used to chain calls.
+     */
+    public EqualsBuilder append(int[] lhs, int[] rhs) {
+        if (isEquals == false) {
+            return this;
+        }
+        if (lhs == rhs) {
+            return this;
+        }
+        if (lhs == null || rhs == null) {
+            isEquals = false;
+            return this;
+        }
+        if (lhs.length != rhs.length) {
+            isEquals = false;
+            return this;
+        }
+        for (int i = 0; i < lhs.length && isEquals; ++i) {
+            append(lhs[i], rhs[i]);
+        }
+        return this;
+    }
+
+    /**
+     * Deep comparison of array of short. Length and all
+     * values are compared.
+     *
+     * The method {@link #append(short, short)} is used.
+     *
+     * @param lhs  the left hand short[]
+     * @param rhs  the right hand short[]
+     * @return EqualsBuilder - used to chain calls.
+     */
+    public EqualsBuilder append(short[] lhs, short[] rhs) {
+        if (isEquals == false) {
+            return this;
+        }
+        if (lhs == rhs) {
+            return this;
+        }
+        if (lhs == null || rhs == null) {
+            isEquals = false;
+            return this;
+        }
+        if (lhs.length != rhs.length) {
+            isEquals = false;
+            return this;
+        }
+        for (int i = 0; i < lhs.length && isEquals; ++i) {
+            append(lhs[i], rhs[i]);
+        }
+        return this;
+    }
+
+    /**
+     * Deep comparison of array of char. Length and all
+     * values are compared.
+     *
+     * The method {@link #append(char, char)} is used.
+     *
+     * @param lhs  the left hand char[]
+     * @param rhs  the right hand char[]
+     * @return EqualsBuilder - used to chain calls.
+     */
+    public EqualsBuilder append(char[] lhs, char[] rhs) {
+        if (isEquals == false) {
+            return this;
+        }
+        if (lhs == rhs) {
+            return this;
+        }
+        if (lhs == null || rhs == null) {
+            isEquals = false;
+            return this;
+        }
+        if (lhs.length != rhs.length) {
+            isEquals = false;
+            return this;
+        }
+        for (int i = 0; i < lhs.length && isEquals; ++i) {
+            append(lhs[i], rhs[i]);
+        }
+        return this;
+    }
+
+    /**
+     * Deep comparison of array of byte. Length and all
+     * values are compared.
+     *
+     * The method {@link #append(byte, byte)} is used.
+     *
+     * @param lhs  the left hand byte[]
+     * @param rhs  the right hand byte[]
+     * @return EqualsBuilder - used to chain calls.
+     */
+    public EqualsBuilder append(byte[] lhs, byte[] rhs) {
+        if (isEquals == false) {
+            return this;
+        }
+        if (lhs == rhs) {
+            return this;
+        }
+        if (lhs == null || rhs == null) {
+            isEquals = false;
+            return this;
+        }
+        if (lhs.length != rhs.length) {
+            isEquals = false;
+            return this;
+        }
+        for (int i = 0; i < lhs.length && isEquals; ++i) {
+            append(lhs[i], rhs[i]);
+        }
+        return this;
+    }
+
+    /**
+     * Deep comparison of array of double. Length and all
+     * values are compared.
+     *
+     * The method {@link #append(double, double)} is used.
+     *
+     * @param lhs  the left hand double[]
+     * @param rhs  the right hand double[]
+     * @return EqualsBuilder - used to chain calls.
+     */
+    public EqualsBuilder append(double[] lhs, double[] rhs) {
+        if (isEquals == false) {
+            return this;
+        }
+        if (lhs == rhs) {
+            return this;
+        }
+        if (lhs == null || rhs == null) {
+            isEquals = false;
+            return this;
+        }
+        if (lhs.length != rhs.length) {
+            isEquals = false;
+            return this;
+        }
+        for (int i = 0; i < lhs.length && isEquals; ++i) {
+            append(lhs[i], rhs[i]);
+        }
+        return this;
+    }
+
+    /**
+     * Deep comparison of array of float. Length and all
+     * values are compared.
+     *
+     * The method {@link #append(float, float)} is used.
+     *
+     * @param lhs  the left hand float[]
+     * @param rhs  the right hand float[]
+     * @return EqualsBuilder - used to chain calls.
+     */
+    public EqualsBuilder append(float[] lhs, float[] rhs) {
+        if (isEquals == false) {
+            return this;
+        }
+        if (lhs == rhs) {
+            return this;
+        }
+        if (lhs == null || rhs == null) {
+            isEquals = false;
+            return this;
+        }
+        if (lhs.length != rhs.length) {
+            isEquals = false;
+            return this;
+        }
+        for (int i = 0; i < lhs.length && isEquals; ++i) {
+            append(lhs[i], rhs[i]);
+        }
+        return this;
+    }
+
+    /**
+     * Deep comparison of array of boolean. Length and all
+     * values are compared.
+     *
+     * The method {@link #append(boolean, boolean)} is used.
+     *
+     * @param lhs  the left hand boolean[]
+     * @param rhs  the right hand boolean[]
+     * @return EqualsBuilder - used to chain calls.
+     */
+    public EqualsBuilder append(boolean[] lhs, boolean[] rhs) {
+        if (isEquals == false) {
+            return this;
+        }
+        if (lhs == rhs) {
+            return this;
+        }
+        if (lhs == null || rhs == null) {
+            isEquals = false;
+            return this;
+        }
+        if (lhs.length != rhs.length) {
+            isEquals = false;
+            return this;
+        }
+        for (int i = 0; i < lhs.length && isEquals; ++i) {
+            append(lhs[i], rhs[i]);
+        }
+        return this;
+    }
+
+    /**
+     * Return true if the fields that have been checked
+     * are all equal.
+     *
+     * @return boolean
+     */
+    public boolean isEquals() {
+        return isEquals;
+    }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/HashCodeBuilder.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/builder/HashCodeBuilder.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/HashCodeBuilder.java	30 Aug 2012 16:24:43 -0000	1.1
@@ -0,0 +1,671 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang.builder;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+
+/**
+ * Assists in implementing {@link Object#hashCode()} methods.
+ *
+ *  This class enables a good hashCode method to be built for any class. It
+ * follows the rules laid out in the book
+ * Effective Java
+ * by Joshua Bloch. Writing a good hashCode method is actually quite
+ * difficult. This class aims to simplify the process.
+ *
+ * All relevant fields from the object should be included in the
+ * hashCode method. Derived fields may be excluded. In general, any
+ * field used in the equals method must be used in the hashCode
+ * method.
+ *
+ * To use this class write code as follows:
+ * 
+ * public class Person {
+ *   String name;
+ *   int age;
+ *   boolean isSmoker;
+ *   ...
+ *
+ *   public int hashCode() {
+ *     // you pick a hard-coded, randomly chosen, non-zero, odd number
+ *     // ideally different for each class
+ *     return new HashCodeBuilder(17, 37).
+ *       append(name).
+ *       append(age).
+ *       append(smoker).
+ *       toHashCode();
+ *   }
+ * }
+ * 
+ *
+ * If required, the superclass hashCode() can be added
+ * using {@link #appendSuper}.
+ *
+ * Alternatively, there is a method that uses reflection to determine
+ * the fields to test. Because these fields are usually private, the method,
+ * reflectionHashCode, uses AccessibleObject.setAccessible to
+ * change the visibility of the fields. This will fail under a security manager,
+ * unless the appropriate permissions are set up correctly. It is also slower
+ * than testing explicitly.
+ *
+ * A typical invocation for this method would look like:
+ * 
+ * public int hashCode() {
+ *   return HashCodeBuilder.reflectionHashCode(this);
+ * }
+ * 
+ *
+ * @author Stephen Colebourne
+ * @author Gary Gregory
+ * @author Pete Gieser
+ * @since 1.0
+ * @version $Id: HashCodeBuilder.java,v 1.1 2012/08/30 16:24:43 marcin Exp $
+ */
+public class HashCodeBuilder {
+
+    /**
+     * Constant to use in building the hashCode.
+     */
+    private final int iConstant;
+    /**
+     * Running total of the hashCode.
+     */
+    private int iTotal = 0;
+
+    /**
+     * Constructor.
+     *
+     * This constructor uses two hard coded choices for the constants
+     * needed to build a hashCode.
+     */
+    public HashCodeBuilder() {
+        super();
+        iConstant = 37;
+        iTotal = 17;
+    }
+
+    /**
+     * Constructor.
+     *
+     * Two randomly chosen, non-zero, odd numbers must be passed in.
+     * Ideally these should be different for each class, however this is
+     * not vital.
+     *
+     * Prime numbers are preferred, especially for the multiplier.
+     *
+     * @param initialNonZeroOddNumber  a non-zero, odd number used as the initial value
+     * @param multiplierNonZeroOddNumber  a non-zero, odd number used as the multiplier
+     * @throws IllegalArgumentException if the number is zero or even
+     */
+    public HashCodeBuilder(int initialNonZeroOddNumber, int multiplierNonZeroOddNumber) {
+        super();
+        if (initialNonZeroOddNumber == 0) {
+            throw new IllegalArgumentException("HashCodeBuilder requires a non zero initial value");
+        }
+        if (initialNonZeroOddNumber % 2 == 0) {
+            throw new IllegalArgumentException("HashCodeBuilder requires an odd initial value");
+        }
+        if (multiplierNonZeroOddNumber == 0) {
+            throw new IllegalArgumentException("HashCodeBuilder requires a non zero multiplier");
+        }
+        if (multiplierNonZeroOddNumber % 2 == 0) {
+            throw new IllegalArgumentException("HashCodeBuilder requires an odd multiplier");
+        }
+        iConstant = multiplierNonZeroOddNumber;
+        iTotal = initialNonZeroOddNumber;
+    }
+
+    //-------------------------------------------------------------------------
+
+    /**
+     * This method uses reflection to build a valid hash code.
+     *
+     * This constructor uses two hard coded choices for the constants
+     * needed to build a hash code.
+     *
+     * It uses AccessibleObject.setAccessible to gain access to private
+     * fields. This means that it will throw a security exception if run under
+     * a security manager, if the permissions are not set up correctly. It is
+     * also not as efficient as testing explicitly.
+     *
+     * Transient members will be not be used, as they are likely derived
+     * fields, and not part of the value of the Object.
+     *
+     * Static fields will not be tested. Superclass fields will be included.
+     *
+     * @param object  the Object to create a hashCode for
+     * @return int hash code
+     * @throws IllegalArgumentException if the object is null
+     */
+    public static int reflectionHashCode(Object object) {
+        return reflectionHashCode(17, 37, object, false, null);
+    }
+
+    /**
+     * This method uses reflection to build a valid hash code.
+     *
+     * This constructor uses two hard coded choices for the constants needed
+     * to build a hash code.
+     *
+     *  It uses AccessibleObject.setAccessible to gain access to private
+     * fields. This means that it will throw a security exception if run under
+     * a security manager, if the permissions are not set up correctly. It is
+     * also not as efficient as testing explicitly.
+     *
+     * If the TestTransients parameter is set to true, transient
+     * members will be tested, otherwise they are ignored, as they are likely
+     * derived fields, and not part of the value of the Object.
+     *
+     * Static fields will not be tested. Superclass fields will be included.
+     *
+     * @param object  the Object to create a hashCode for
+     * @param testTransients  whether to include transient fields
+     * @return int hash code
+     * @throws IllegalArgumentException if the object is null
+     */
+    public static int reflectionHashCode(Object object, boolean testTransients) {
+        return reflectionHashCode(17, 37, object, testTransients, null);
+    }
+
+    /**
+     * This method uses reflection to build a valid hash code.
+     *
+     * It uses AccessibleObject.setAccessible to gain access to private
+     * fields. This means that it will throw a security exception if run under
+     * a security manager, if the permissions are not set up correctly. It is
+     * also not as efficient as testing explicitly.
+     *
+     * Transient members will be not be used, as they are likely derived
+     * fields, and not part of the value of the Object.
+     *
+     * Static fields will not be tested. Superclass fields will be included.
+     *
+     * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally
+     * these should be different for each class, however this is not vital.
+     * Prime numbers are preferred, especially for the multiplier.
+     *
+     * @param initialNonZeroOddNumber  a non-zero, odd number used as the initial value
+     * @param multiplierNonZeroOddNumber  a non-zero, odd number used as the multiplier
+     * @param object  the Object to create a hashCode for
+     * @return int hash code
+     * @throws IllegalArgumentException if the Object is null
+     * @throws IllegalArgumentException if the number is zero or even
+     */
+    public static int reflectionHashCode(
+            int initialNonZeroOddNumber, int multiplierNonZeroOddNumber, Object object) {
+        return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, false, null);
+    }
+
+    /**
+     * This method uses reflection to build a valid hash code.
+     *
+     * It uses AccessibleObject.setAccessible to gain access to private
+     * fields. This means that it will throw a security exception if run under
+     * a security manager, if the permissions are not set up correctly. It is also
+     * not as efficient as testing explicitly.
+     *
+     * If the TestTransients parameter is set to true, transient
+     * members will be tested, otherwise they are ignored, as they are likely
+     * derived fields, and not part of the value of the Object.
+     *
+     * Static fields will not be tested. Superclass fields will be included.
+     *
+     * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally
+     * these should be different for each class, however this is not vital.
+     * Prime numbers are preferred, especially for the multiplier.
+     *
+     * @param initialNonZeroOddNumber  a non-zero, odd number used as the initial value
+     * @param multiplierNonZeroOddNumber  a non-zero, odd number used as the multiplier
+     * @param object  the Object to create a hashCode for
+     * @param testTransients  whether to include transient fields
+     * @return int hash code
+     * @throws IllegalArgumentException if the Object is null
+     * @throws IllegalArgumentException if the number is zero or even
+     */
+    public static int reflectionHashCode(
+            int initialNonZeroOddNumber, int multiplierNonZeroOddNumber,
+            Object object, boolean testTransients) {
+        return reflectionHashCode(initialNonZeroOddNumber, multiplierNonZeroOddNumber, object, testTransients, null);
+    }
+            
+    /**
+     * This method uses reflection to build a valid hash code.
+     *
+     * It uses AccessibleObject.setAccessible to gain access to private
+     * fields. This means that it will throw a security exception if run under
+     * a security manager, if the permissions are not set up correctly. It is also
+     * not as efficient as testing explicitly.
+     *
+     * If the TestTransients parameter is set to true, transient
+     * members will be tested, otherwise they are ignored, as they are likely
+     * derived fields, and not part of the value of the Object.
+     *
+     * Static fields will not be included. Superclass fields will be included
+     * up to and including the specified superclass. A null superclass is treated
+     * as java.lang.Object.
+     *
+     * Two randomly chosen, non-zero, odd numbers must be passed in. Ideally
+     * these should be different for each class, however this is not vital.
+     * Prime numbers are preferred, especially for the multiplier.
+     *
+     * @param initialNonZeroOddNumber  a non-zero, odd number used as the initial value
+     * @param multiplierNonZeroOddNumber  a non-zero, odd number used as the multiplier
+     * @param object  the Object to create a hashCode for
+     * @param testTransients  whether to include transient fields
+     * @param reflectUpToClass  the superclass to reflect up to (inclusive),
+     *  may be null
+     * @return int hash code
+     * @throws IllegalArgumentException if the Object is null
+     * @throws IllegalArgumentException if the number is zero or even
+     * @since 2.0
+     */
+    public static int reflectionHashCode(
+        int initialNonZeroOddNumber,
+        int multiplierNonZeroOddNumber,
+        Object object,
+        boolean testTransients,
+        Class reflectUpToClass) {
+
+        if (object == null) {
+            throw new IllegalArgumentException("The object to build a hash code for must not be null");
+        }
+        HashCodeBuilder builder = new HashCodeBuilder(initialNonZeroOddNumber, multiplierNonZeroOddNumber);
+        Class clazz = object.getClass();
+        reflectionAppend(object, clazz, builder, testTransients);
+        while (clazz.getSuperclass() != null && clazz != reflectUpToClass) {
+            clazz = clazz.getSuperclass();
+            reflectionAppend(object, clazz, builder, testTransients);
+        }
+        return builder.toHashCode();
+    }
+
+    /**
+     * Appends the fields and values defined by the given object of the
+     * given Class.
+     * 
+     * @param object  the object to append details of
+     * @param clazz  the class to append details of
+     * @param builder  the builder to append to
+     * @param useTransients  whether to use transient fields
+     */
+    private static void reflectionAppend(Object object, Class clazz, HashCodeBuilder builder, boolean useTransients) {
+        Field[] fields = clazz.getDeclaredFields();
+        AccessibleObject.setAccessible(fields, true);
+        for (int i = 0; i < fields.length; i++) {
+            Field f = fields[i];
+            if ((f.getName().indexOf('$') == -1)
+                && (useTransients || !Modifier.isTransient(f.getModifiers()))
+                && (!Modifier.isStatic(f.getModifiers()))) {
+                try {
+                    builder.append(f.get(object));
+                } catch (IllegalAccessException e) {
+                    //this can't happen. Would get a Security exception instead
+                    //throw a runtime exception in case the impossible happens.
+                    throw new InternalError("Unexpected IllegalAccessException");
+                }
+            }
+        }
+    }
+
+    //-------------------------------------------------------------------------
+
+    /**
+     * Adds the result of super.hashCode() to this builder.
+     *
+     * @param superHashCode  the result of calling super.hashCode()
+     * @return this HashCodeBuilder, used to chain calls.
+     * @since 2.0
+     */
+    public HashCodeBuilder appendSuper(int superHashCode) {
+        iTotal = iTotal * iConstant + superHashCode;
+        return this;
+    }
+
+    //-------------------------------------------------------------------------
+
+    /**
+     * Append a hashCode for an Object.
+     *
+     * @param object  the Object to add to the hashCode
+     * @return this
+     */
+    public HashCodeBuilder append(Object object) {
+        if (object == null) {
+            iTotal = iTotal * iConstant;
+
+        } else {
+            if (object.getClass().isArray() == false) {
+                //the simple case, not an array, just the element
+                iTotal = iTotal * iConstant + object.hashCode();
+
+            } else {
+                //'Switch' on type of array, to dispatch to the correct handler
+                // This handles multi dimensional arrays
+                if (object instanceof long[]) {
+                    append((long[]) object);
+                } else if (object instanceof int[]) {
+                    append((int[]) object);
+                } else if (object instanceof short[]) {
+                    append((short[]) object);
+                } else if (object instanceof char[]) {
+                    append((char[]) object);
+                } else if (object instanceof byte[]) {
+                    append((byte[]) object);
+                } else if (object instanceof double[]) {
+                    append((double[]) object);
+                } else if (object instanceof float[]) {
+                    append((float[]) object);
+                } else if (object instanceof boolean[]) {
+                    append((boolean[]) object);
+                } else {
+                    // Not an array of primitives
+                    append((Object[]) object);
+                }
+            }
+        }
+        return this;
+    }
+
+    /**
+     * Append a hashCode for a long.
+     *
+     * @param value  the long to add to the hashCode
+     * @return this
+     */
+    public HashCodeBuilder append(long value) {
+        iTotal = iTotal * iConstant + ((int) (value ^ (value >> 32)));
+        return this;
+    }
+
+    /**
+     * Append a hashCode for an int.
+     *
+     * @param value  the int to add to the hashCode
+     * @return this
+     */
+    public HashCodeBuilder append(int value) {
+        iTotal = iTotal * iConstant + value;
+        return this;
+    }
+
+    /**
+     * Append a hashCode for a short.
+     *
+     * @param value  the short to add to the hashCode
+     * @return this
+     */
+    public HashCodeBuilder append(short value) {
+        iTotal = iTotal * iConstant + value;
+        return this;
+    }
+
+    /**
+     * Append a hashCode for a char.
+     *
+     * @param value  the char to add to the hashCode
+     * @return this
+     */
+    public HashCodeBuilder append(char value) {
+        iTotal = iTotal * iConstant + value;
+        return this;
+    }
+
+    /**
+     * Append a hashCode for a byte.
+     *
+     * @param value  the byte to add to the hashCode
+     * @return this
+     */
+    public HashCodeBuilder append(byte value) {
+        iTotal = iTotal * iConstant + value;
+        return this;
+    }
+
+    /**
+     * Append a hashCode for a double.
+     *
+     * @param value  the double to add to the hashCode
+     * @return this
+     */
+    public HashCodeBuilder append(double value) {
+        return append(Double.doubleToLongBits(value));
+    }
+
+    /**
+     * Append a hashCode for a float.
+     *
+     * @param value  the float to add to the hashCode
+     * @return this
+     */
+    public HashCodeBuilder append(float value) {
+        iTotal = iTotal * iConstant + Float.floatToIntBits(value);
+        return this;
+    }
+
+    /**
+     * Append a hashCode for a boolean.
+     *
+     * @param value  the boolean to add to the hashCode
+     * @return this
+     */
+    public HashCodeBuilder append(boolean value) {
+        iTotal = iTotal * iConstant + (value ? 0 : 1);
+        return this;
+    }
+
+    /**
+     * Append a hashCode for an Object array.
+     *
+     * @param array  the array to add to the hashCode
+     * @return this
+     */
+    public HashCodeBuilder append(Object[] array) {
+        if (array == null) {
+            iTotal = iTotal * iConstant;
+        } else {
+            for (int i = 0; i < array.length; i++) {
+                append(array[i]);
+            }
+        }
+        return this;
+    }
+
+    /**
+     * Append a hashCode for a long array.
+     *
+     * @param array  the array to add to the hashCode
+     * @return this
+     */
+    public HashCodeBuilder append(long[] array) {
+        if (array == null) {
+            iTotal = iTotal * iConstant;
+        } else {
+            for (int i = 0; i < array.length; i++) {
+                append(array[i]);
+            }
+        }
+        return this;
+    }
+
+    /**
+     * Append a hashCode for an int array.
+     *
+     * @param array  the array to add to the hashCode
+     * @return this
+     */
+    public HashCodeBuilder append(int[] array) {
+        if (array == null) {
+            iTotal = iTotal * iConstant;
+        } else {
+            for (int i = 0; i < array.length; i++) {
+                append(array[i]);
+            }
+        }
+        return this;
+    }
+
+    /**
+     * Append a hashCode for a short array.
+     *
+     * @param array  the array to add to the hashCode
+     * @return this
+     */
+    public HashCodeBuilder append(short[] array) {
+        if (array == null) {
+            iTotal = iTotal * iConstant;
+        } else {
+            for (int i = 0; i < array.length; i++) {
+                append(array[i]);
+            }
+        }
+        return this;
+    }
+
+    /**
+     * Append a hashCode for a char array.
+     *
+     * @param array  the array to add to the hashCode
+     * @return this
+     */
+    public HashCodeBuilder append(char[] array) {
+        if (array == null) {
+            iTotal = iTotal * iConstant;
+        } else {
+            for (int i = 0; i < array.length; i++) {
+                append(array[i]);
+            }
+        }
+        return this;
+    }
+
+    /**
+     * Append a hashCode for a byte array.
+     *
+     * @param array  the array to add to the hashCode
+     * @return this
+     */
+    public HashCodeBuilder append(byte[] array) {
+        if (array == null) {
+            iTotal = iTotal * iConstant;
+        } else {
+            for (int i = 0; i < array.length; i++) {
+                append(array[i]);
+            }
+        }
+        return this;
+    }
+
+    /**
+     * Append a hashCode for a double array.
+     *
+     * @param array  the array to add to the hashCode
+     * @return this
+     */
+    public HashCodeBuilder append(double[] array) {
+        if (array == null) {
+            iTotal = iTotal * iConstant;
+        } else {
+            for (int i = 0; i < array.length; i++) {
+                append(array[i]);
+            }
+        }
+        return this;
+    }
+
+    /**
+     * Append a hashCode for a float array.
+     *
+     * @param array  the array to add to the hashCode
+     * @return this
+     */
+    public HashCodeBuilder append(float[] array) {
+        if (array == null) {
+            iTotal = iTotal * iConstant;
+        } else {
+            for (int i = 0; i < array.length; i++) {
+                append(array[i]);
+            }
+        }
+        return this;
+    }
+
+    /**
+     * Append a hashCode for a boolean array.
+     *
+     * @param array  the array to add to the hashCode
+     * @return this
+     */
+    public HashCodeBuilder append(boolean[] array) {
+        if (array == null) {
+            iTotal = iTotal * iConstant;
+        } else {
+            for (int i = 0; i < array.length; i++) {
+                append(array[i]);
+            }
+        }
+        return this;
+    }
+
+    /**
+     * Return the computed hashCode.
+     *
+     * @return hashCode based on the fields appended
+     */
+    public int toHashCode() {
+        return iTotal;
+    }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/ReflectionToStringBuilder.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/builder/ReflectionToStringBuilder.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/ReflectionToStringBuilder.java	30 Aug 2012 16:24:43 -0000	1.1
@@ -0,0 +1,535 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang.builder;
+
+import java.lang.reflect.AccessibleObject;
+import java.lang.reflect.Field;
+import java.lang.reflect.Modifier;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.commons.lang.ClassUtils;
+
+/**
+ * Assists in implementing {@link Object#toString()} methods using reflection.
+ *
+ * This class uses reflection to determine the fields to append. 
+ * Because these fields are usually private, the class 
+ * uses AccessibleObject.setAccessible to
+ * change the visibility of the fields. This will fail under a security manager,
+ * unless the appropriate permissions are set up correctly.
+ *
+ * A typical invocation for this method would look like:
+ * 
+ * public String toString() {
+ *   return ReflectionToStringBuilder.toString(this);
+ * }
+ *
+ * You can also use the builder to debug 3rd party objects:
+ * 
+ * System.out.println("An object: " + ReflectionToStringBuilder.toString(anObject));
+ * 
+ * A subclass can control field output by overriding the methods:
+ * 
 
+ *  - {@link #accept(java.lang.reflect.Field)}
 
+ *  - {@link #getValue(java.lang.reflect.Field)}
 
+ * 
+ * 
+ * For example, this method does not include the password field in the returned 
+ * String:
+ * 
+ * public String toString() {
+ *     return (new ReflectionToStringBuilder(this) {
+ *         protected boolean accept(Field f) {
+ *             return super.accept(f) && !f.getName().equals("password");
+ *         }
+ *     }).toString();
+ * }
+ * 
+ * The exact format of the toString is determined by
+ * the {@link ToStringStyle} passed into the constructor.
+ *
+ * @author Gary Gregory
+ * @author Stephen Colebourne
+ * @author Pete Gieser
+ * @since 2.0
+ * @version $Id: ReflectionToStringBuilder.java,v 1.1 2012/08/30 16:24:43 marcin Exp $
+ */
+public class ReflectionToStringBuilder extends ToStringBuilder {
+
+    /**
+     * A registry of objects used by reflectionToString methods
+     * to detect cyclical object references and avoid infinite loops.
+     */
+    private static ThreadLocal registry = new ThreadLocal() {
+        protected synchronized Object initialValue() {
+            // The HashSet implementation is not synchronized, 
+            // which is just what we need here. 
+            return new HashSet();
+        }
+    };
+
+    /**
+     * Returns the registry of objects being traversed by the
+     * reflectionToString methods in the current thread.
+     *
+     * @return Set the registry of objects being traversed 
+     */
+    static Set getRegistry() {
+        return (Set) registry.get();
+    }
+
+    /**
+     * Returns true if the registry contains the given object.
+     * Used by the reflection methods to avoid infinite loops.
+     * 
+     * @param value The object to lookup in the registry.
+     * @return boolean true if the registry contains the given object.
+     */
+    static boolean isRegistered(Object value) {
+        return getRegistry().contains(value);
+    }
+
+    /**
+     * Registers the given object.
+     * Used by the reflection methods to avoid infinite loops.
+     * 
+     * @param value The object to register.
+     */
+    static void register(Object value) {
+        getRegistry().add(value);
+    }
+    
+    /**
+     * This method uses reflection to build a suitable
+     * toString using the default ToStringStyle.
+     *
+     * 
It uses AccessibleObject.setAccessible to gain access to private
+     * fields. This means that it will throw a security exception if run
+     * under a security manager, if the permissions are not set up correctly.
+     * It is also not as efficient as testing explicitly.
+     *
+     * Transient members will be not be included, as they are likely derived.
+     * Static fields will not be included. Superclass fields will be appended.
+     *
+     * @param object  the Object to be output
+     * @return the String result
+     * @throws IllegalArgumentException if the Object is null
+     */
+    public static String toString(Object object) {
+        return toString(object, null, false, null);
+    }
+
+    /**
+     * This method uses reflection to build a suitable
+     * toString.
+     *
+     * It uses AccessibleObject.setAccessible to gain access to private
+     * fields. This means that it will throw a security exception if run
+     * under a security manager, if the permissions are not set up correctly.
+     * It is also not as efficient as testing explicitly.
+     *
+     * Transient members will be not be included, as they are likely derived.
+     * Static fields will not be included. Superclass fields will be appended.
+     *
+     * If the style is null, the default
+     * ToStringStyle is used.
+     * 
+     * @param object  the Object to be output
+     * @param style  the style of the toString to create,
+     *  may be null
+     * @return the String result
+     * @throws IllegalArgumentException if the Object or
+     *  ToStringStyle is null
+     */
+    public static String toString(Object object, ToStringStyle style) {
+        return toString(object, style, false, null);
+    }
+
+    /**
+     * This method uses reflection to build a suitable
+     * toString.
+     *
+     * It uses AccessibleObject.setAccessible to gain access to private
+     * fields. This means that it will throw a security exception if run
+     * under a security manager, if the permissions are not set up correctly.
+     * It is also not as efficient as testing explicitly. 
+     *
+     * If the outputTransients is true,
+     * transient members will be output, otherwise they are ignored,
+     * as they are likely derived fields, and not part of the value of the
+     * Object.
+     *
+     * Static fields will not be included. Superclass fields will be appended.
+     *
+     * If the style is null, the default
+     * ToStringStyle is used.
+     * 
+     * @param object  the Object to be output
+     * @param style  the style of the toString to create,
+     *  may be null
+     * @param outputTransients  whether to include transient fields
+     * @return the String result
+     * @throws IllegalArgumentException if the Object is null
+     */
+    public static String toString(Object object, ToStringStyle style, boolean outputTransients) {
+        return toString(object, style, outputTransients, null);
+    }
+
+    /**
+     * This method uses reflection to build a suitable
+     * toString.
+     *
+     * It uses AccessibleObject.setAccessible to gain access to private
+     * fields. This means that it will throw a security exception if run
+     * under a security manager, if the permissions are not set up correctly.
+     * It is also not as efficient as testing explicitly. 
+     *
+     * If the outputTransients is true,
+     * transient members will be output, otherwise they are ignored,
+     * as they are likely derived fields, and not part of the value of the
+     * Object.
+     *
+     * Static fields will not be included. Superclass fields will be appended
+     * up to and including the specified superclass. A null superclass is treated
+     * as java.lang.Object.
+     *
+     * If the style is null, the default
+     * ToStringStyle is used.
+     * 
+     * @param object  the Object to be output
+     * @param style  the style of the toString to create,
+     *  may be null
+     * @param outputTransients  whether to include transient fields
+     * @param reflectUpToClass  the superclass to reflect up to (inclusive),
+     *  may be null
+     * @return the String result
+     * @throws IllegalArgumentException if the Object is null
+     */
+    public static String toString(
+        Object object,
+        ToStringStyle style,
+        boolean outputTransients,
+        Class reflectUpToClass) {
+        return new ReflectionToStringBuilder(object, style, null, reflectUpToClass, outputTransients).toString();
+    }
+
+    /**
+     * Unregisters the given object.
+     *
+     * Used by the reflection methods to avoid infinite loops.
+     * 
+     * @param value The object to unregister.
+     */
+    static void unregister(Object value) {
+        getRegistry().remove(value);
+    }
+
+    /**
+     * Whether or not to append transient fields.
+     */
+    private boolean appendTransients = false;
+
+    /**
+     * The last super class to stop appending fields for.
+     */
+    private Class upToClass = null;
+
+    /**
+     * Constructor.
+     *
+     * This constructor outputs using the default style set with
+     * setDefaultStyle.
+     * 
+     * @param object  the Object to build a toString for,
+     *  must not be null
+     * @throws IllegalArgumentException  if the Object passed in is
+     *  null
+     */
+    public ReflectionToStringBuilder(Object object) {
+        super(object);
+    }
+
+    /**
+     * Constructor.
+     *
+     * If the style is null, the default style is used.
+     * 
+     * @param object  the Object to build a toString for,
+     *  must not be null
+     * @param style  the style of the toString to create,
+     *  may be null
+     * @throws IllegalArgumentException  if the Object passed in is
+     *  null
+     */
+    public ReflectionToStringBuilder(Object object, ToStringStyle style) {
+        super(object, style);
+    }
+
+    /**
+     * Constructor.
+     *
+     * If the style is null, the default style is used.
+     *
+     * If the buffer is null, a new one is created.
+     * 
+     * @param object  the Object to build a toString for,
+     *  must not be null
+     * @param style  the style of the toString to create,
+     *  may be null
+     * @param buffer  the StringBuffer to populate, may be
+     *  null
+     * @throws IllegalArgumentException  if the Object passed in is
+     *  null
+     */
+    public ReflectionToStringBuilder(Object object, ToStringStyle style, StringBuffer buffer) {
+        super(object, style, buffer);
+    }
+
+    /**
+     * Constructor.
+     * 
+     * @param object  the Object to build a toString for,
+     *  must not be null
+     * @param style  the style of the toString to create,
+     *  may be null
+     * @param buffer  the StringBuffer to populate, may be
+     *  null
+     * @param reflectUpToClass  the superclass to reflect up to (inclusive),
+     *  may be null
+     * @param outputTransients  whether to include transient fields
+     */
+    public ReflectionToStringBuilder(
+        Object object,
+        ToStringStyle style,
+        StringBuffer buffer,
+        Class reflectUpToClass,
+        boolean outputTransients) {
+        super(object, style, buffer);
+        this.setUpToClass(reflectUpToClass);
+        this.setAppendTransients(outputTransients);
+    }
+
+    /**
+     * Returns whether or not to append the given Field.
+     * 
+     *  - Static fields are not appended.
 
+     *  - Transient fields are appended only if {@link #isAppendTransients()} returns 
true.
+     *   - Inner class fields are not appened.
 
+     * 
+     * @param field The Field to test.
+     * @return Whether or not to append the given Field.
+     */
+    protected boolean accept(Field field) {
+        String fieldName = field.getName();
+        return (fieldName.indexOf(ClassUtils.INNER_CLASS_SEPARATOR_CHAR) == -1)
+            && (this.isAppendTransients() || !Modifier.isTransient(field.getModifiers()))
+            && (!Modifier.isStatic(field.getModifiers()));
+    }
+
+    /**
+     * Appends the fields and values defined by the given object of the
+     * given Class.
+     *
+     * If a cycle is detected as an object is "toString()'ed",
+     * such an object is rendered as if Object.toString() 
+     * had been called and not implemented by the object.
+     * 
+     * @param clazz The class of object parameter
+     */
+    protected void appendFieldsIn(Class clazz) {
+        if (isRegistered(this.getObject())) {
+            // The object has already been appended, therefore we have an object cycle. 
+            // Append a simple Object.toString style string. The field name is already appended at this point.
+            this.appendAsObjectToString(this.getObject());
+            return;
+        }
+        try {
+            this.registerObject();
+            if (clazz.isArray()) {
+                this.reflectionAppendArray(this.getObject());
+                return;
+            }
+            Field[] fields = clazz.getDeclaredFields();
+            AccessibleObject.setAccessible(fields, true);
+            for (int i = 0; i < fields.length; i++) {
+                Field field = fields[i];
+                String fieldName = field.getName();
+                if (this.accept(field)) {
+                    try {
+                        // Warning: Field.get(Object) creates wrappers objects for primitive types.
+                        Object fieldValue = this.getValue(field);
+                        if (isRegistered(fieldValue) && !field.getType().isPrimitive()) {
+                            // A known field value has already been appended, therefore we have an object cycle, 
+                            // append a simple Object.toString style string.
+                            this.getStyle().appendFieldStart(this.getStringBuffer(), fieldName);
+                            this.appendAsObjectToString(fieldValue);
+                            // The recursion out of 
+                            //    builder.append(fieldName, fieldValue); 
+                            // below will append the field 
+                            // end marker.
+                        } else {
+                            try {
+                                this.registerObject();
+                                this.append(fieldName, fieldValue);
+                            } finally {
+                                this.unregisterObject();
+                            }
+                        }
+                    } catch (IllegalAccessException ex) {
+                        //this can't happen. Would get a Security exception instead
+                        //throw a runtime exception in case the impossible happens.
+                        throw new InternalError("Unexpected IllegalAccessException: " + ex.getMessage());
+                    }
+                }
+            }
+        } finally {
+            this.unregisterObject();
+        }
+    }
+    
+    /**
+     * Gets the last super class to stop appending fields for.
+     * 
+     * @return The last super class to stop appending fields for.
+     */
+    public Class getUpToClass() {
+        return this.upToClass;
+    }
+
+    /**
+     * Calls java.lang.reflect.Field.get(Object).
+     *
+     * @see java.lang.reflect.Field#get(Object)
+     * @throws IllegalArgumentException
+     * @throws IllegalAccessException
+     */
+    protected Object getValue(Field field) throws IllegalArgumentException, IllegalAccessException {
+        return field.get(this.getObject());
+    }
+
+    /**
+     * Gets whether or not to append transient fields.
+     * 
+     * @return Whether or not to append transient fields.
+     */
+    public boolean isAppendTransients() {
+        return this.appendTransients;
+    }
+    
+    /**
+     * Append to the toString an Object
+     * array.
+     *
+     * @param array  the array to add to the toString
+     * @return this
+     */
+    public ToStringBuilder reflectionAppendArray(Object array) {
+        this.getStyle().reflectionAppendArrayDetail(this.getStringBuffer(), null, array);
+        return this;
+    }
+
+    /**
+     * Registers this builder's source object to avoid infinite
+     * loops when processing circular object references.
+     */
+    void registerObject() {
+        register(this.getObject());
+    }
+
+    /**
+     * Sets whether or not to append transient fields.
+     * 
+     * @param appendTransients Whether or not to append transient fields.
+     */
+    public void setAppendTransients(boolean appendTransients) {
+        this.appendTransients = appendTransients;
+    }
+
+    /**
+     * Sets the last super class to stop appending fields for.
+     * 
+     * @param clazz The last super class to stop appending fields for.
+     */
+    public void setUpToClass(Class clazz) {
+        this.upToClass = clazz;
+    }
+
+    /**
+     * Gets the String built by this builder.
+     *
+     * @return the built string
+     */
+    public String toString() {
+        if (this.getObject() == null) {
+            return this.getStyle().getNullText();
+        }
+        Class clazz = this.getObject().getClass();
+        this.appendFieldsIn(clazz);
+        while (clazz.getSuperclass() != null && clazz != this.getUpToClass()) {
+            clazz = clazz.getSuperclass();
+            this.appendFieldsIn(clazz);
+        }
+        return super.toString();
+    }
+
+    /**
+     * Unegisters this builder's source object to avoid infinite
+     * loops when processing circular object references.
+     */
+    void unregisterObject() {
+        unregister(this.getObject());
+    }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/StandardToStringStyle.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/builder/StandardToStringStyle.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/StandardToStringStyle.java	30 Aug 2012 16:24:43 -0000	1.1
@@ -0,0 +1,575 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang.builder;
+
+/**
+ * Works with {@link ToStringBuilder} to create a toString.
+ *
+ * This class is intended to be used as a singleton.
+ * There is no need to instantiate a new style each time.
+ * Simply instantiate the class once, customize the values as required, and
+ * store the result in a public static final variable for the rest of the
+ * program to access.
+ *
+ * @author Stephen Colebourne
+ * @author Pete Gieser
+ * @author Gary Gregory
+ * @since 1.0
+ * @version $Id: StandardToStringStyle.java,v 1.1 2012/08/30 16:24:43 marcin Exp $
+ */
+public class StandardToStringStyle extends ToStringStyle {
+    
+    /**
+     * Constructor.
+     */
+    public StandardToStringStyle() {
+        super();
+    }
+    
+    //---------------------------------------------------------------------
+    
+    /**
+     * Gets whether to use the class name.
+     *
+     * @return the current useClassName flag
+     */
+    public boolean isUseClassName() {
+        return super.isUseClassName();
+    }
+
+    /**
+     * Sets whether to use the class name.
+     *
+     * @param useClassName  the new useClassName flag
+     */
+    public void setUseClassName(boolean useClassName) {
+        super.setUseClassName(useClassName);
+    }
+
+    //---------------------------------------------------------------------
+    
+    /**
+     * Gets whether to output short or long class names.
+     *
+     * @return the current useShortClassName flag
+     * @since 2.0
+     */
+    public boolean isUseShortClassName() {
+        return super.isUseShortClassName();
+    }
+
+    /**
+     * Gets whether to output short or long class names.
+     *
+     * @return the current shortClassName flag
+     * @deprecated Use {@link #isUseShortClassName()}
+     *             Method will be removed in Commons Lang 3.0.
+     */
+    public boolean isShortClassName() {
+        return super.isUseShortClassName();
+    }
+
+    /**
+     * Sets whether to output short or long class names.
+     *
+     * @param useShortClassName  the new useShortClassName flag
+     * @since 2.0
+     */
+    public void setUseShortClassName(boolean useShortClassName) {
+        super.setUseShortClassName(useShortClassName);
+    }
+
+    /**
+     * Sets whether to output short or long class names.
+     *
+     * @param shortClassName  the new shortClassName flag
+     * @deprecated Use {@link #setUseShortClassName(boolean)}
+     *             Method will be removed in Commons Lang 3.0.
+     */
+    public void setShortClassName(boolean shortClassName) {
+        super.setUseShortClassName(shortClassName);
+    }
+
+    //---------------------------------------------------------------------
+    
+    /**
+     * Gets whether to use the identity hash code.
+     * @return the current useIdentityHashCode flag
+     */
+    public boolean isUseIdentityHashCode() {
+        return super.isUseIdentityHashCode();
+    }
+
+    /**
+     * Sets whether to use the identity hash code.
+     *
+     * @param useIdentityHashCode  the new useIdentityHashCode flag
+     */
+    public void setUseIdentityHashCode(boolean useIdentityHashCode) {
+        super.setUseIdentityHashCode(useIdentityHashCode);
+    }
+
+    //---------------------------------------------------------------------
+    
+    /**
+     * Gets whether to use the field names passed in.
+     *
+     * @return the current useFieldNames flag
+     */
+    public boolean isUseFieldNames() {
+        return super.isUseFieldNames();
+    }
+
+    /**
+     * Sets whether to use the field names passed in.
+     *
+     * @param useFieldNames  the new useFieldNames flag
+     */
+    public void setUseFieldNames(boolean useFieldNames) {
+        super.setUseFieldNames(useFieldNames);
+    }
+
+    //---------------------------------------------------------------------
+    
+    /**
+     * Gets whether to use full detail when the caller doesn't
+     * specify.
+     *
+     * @return the current defaultFullDetail flag
+     */
+    public boolean isDefaultFullDetail() {
+        return super.isDefaultFullDetail();
+    }
+
+    /**
+     * Sets whether to use full detail when the caller doesn't
+     * specify.
+     *
+     * @param defaultFullDetail  the new defaultFullDetail flag
+     */
+    public void setDefaultFullDetail(boolean defaultFullDetail) {
+        super.setDefaultFullDetail(defaultFullDetail);
+    }
+
+    //---------------------------------------------------------------------
+    
+    /**
+     * Gets whether to output array content detail.
+     *
+     * @return the current array content detail setting
+     */
+    public boolean isArrayContentDetail() {
+        return super.isArrayContentDetail();
+    }
+    
+    /**
+     * Sets whether to output array content detail.
+     *
+     * @param arrayContentDetail  the new arrayContentDetail flag
+     */
+    public void setArrayContentDetail(boolean arrayContentDetail) {
+        super.setArrayContentDetail(arrayContentDetail);
+    }
+
+    //---------------------------------------------------------------------
+    
+    /**
+     * Gets the array start text.
+     *
+     * @return the current array start text
+     */
+    public String getArrayStart() {
+        return super.getArrayStart();
+    }
+
+    /**
+     * Sets the array start text.
+     *
+     * null is accepted, but will be converted
+     * to an empty String.
+     *
+     * @param arrayStart  the new array start text
+     */
+    public void setArrayStart(String arrayStart) {
+        super.setArrayStart(arrayStart);
+    }
+
+    //---------------------------------------------------------------------
+    
+    /**
+     * Gets the array end text.
+     *
+     * @return the current array end text
+     */
+    public String getArrayEnd() {
+        return super.getArrayEnd();
+    }
+
+    /**
+     * Sets the array end text.
+     *
+     * null is accepted, but will be converted
+     * to an empty String.
+     *
+     * @param arrayEnd  the new array end text
+     */
+    public void setArrayEnd(String arrayEnd) {
+        super.setArrayEnd(arrayEnd);
+    }
+
+    //---------------------------------------------------------------------
+    
+    /**
+     * Gets the array separator text.
+     *
+     * @return the current array separator text
+     */
+    public String getArraySeparator() {
+        return super.getArraySeparator();
+    }
+
+    /**
+     * Sets the array separator text.
+     *
+     * null is accepted, but will be converted
+     * to an empty String.
+     *
+     * @param arraySeparator  the new array separator text
+     */
+    public void setArraySeparator(String arraySeparator) {
+        super.setArraySeparator(arraySeparator);
+    }
+
+    //---------------------------------------------------------------------
+    
+    /**
+     * Gets the content start text.
+     *
+     * @return the current content start text
+     */
+    public String getContentStart() {
+        return super.getContentStart();
+    }
+
+    /**
+     * Sets the content start text.
+     *
+     * null is accepted, but will be converted
+     * to an empty String.
+     *
+     * @param contentStart  the new content start text
+     */
+    public void setContentStart(String contentStart) {
+        super.setContentStart(contentStart);
+    }
+
+    //---------------------------------------------------------------------
+    
+    /**
+     * Gets the content end text.
+     *
+     * @return the current content end text
+     */
+    public String getContentEnd() {
+        return super.getContentEnd();
+    }
+
+    /**
+     * Sets the content end text.
+     *
+     * null is accepted, but will be converted
+     * to an empty String.
+     *
+     * @param contentEnd  the new content end text
+     */
+    public void setContentEnd(String contentEnd) {
+        super.setContentEnd(contentEnd);
+    }
+
+    //---------------------------------------------------------------------
+    
+    /**
+     * Gets the field name value separator text.
+     *
+     * @return the current field name value separator text
+     */
+    public String getFieldNameValueSeparator() {
+        return super.getFieldNameValueSeparator();
+    }
+
+    /**
+     * Sets the field name value separator text.
+     *
+     * null is accepted, but will be converted
+     * to an empty String.
+     *
+     * @param fieldNameValueSeparator  the new field name value separator text
+     */
+    public void setFieldNameValueSeparator(String fieldNameValueSeparator) {
+        super.setFieldNameValueSeparator(fieldNameValueSeparator);
+    }
+
+    //---------------------------------------------------------------------
+    
+    /**
+     * Gets the field separator text.
+     *
+     * @return the current field separator text
+     */
+    public String getFieldSeparator() {
+        return super.getFieldSeparator();
+    }
+
+    /**
+     * Sets the field separator text.
+     *
+     * null is accepted, but will be converted
+     * to an empty String.
+     *
+     * @param fieldSeparator  the new field separator text
+     */
+    public void setFieldSeparator(String fieldSeparator) {
+        super.setFieldSeparator(fieldSeparator);
+    }
+
+    //---------------------------------------------------------------------
+    
+    /**
+     * Gets whether the field separator should be added at the start 
+     * of each buffer.
+     * 
+     * @return the fieldSeparatorAtStart flag
+     * @since 2.0
+     */
+    public boolean isFieldSeparatorAtStart() {
+        return super.isFieldSeparatorAtStart();
+    }
+
+    /**
+     * Sets whether the field separator should be added at the start 
+     * of each buffer.
+     * 
+     * @param fieldSeparatorAtStart  the fieldSeparatorAtStart flag
+     * @since 2.0
+     */
+    public void setFieldSeparatorAtStart(boolean fieldSeparatorAtStart) {
+        super.setFieldSeparatorAtStart(fieldSeparatorAtStart);
+    }
+
+    //---------------------------------------------------------------------
+    
+    /**
+     * Gets whether the field separator should be added at the end 
+     * of each buffer.
+     * 
+     * @return fieldSeparatorAtEnd flag
+     * @since 2.0
+     */
+    public boolean isFieldSeparatorAtEnd() {
+        return super.isFieldSeparatorAtEnd();
+    }
+
+    /**
+     * Sets whether the field separator should be added at the end 
+     * of each buffer.
+     * 
+     * @param fieldSeparatorAtEnd  the fieldSeparatorAtEnd flag
+     * @since 2.0
+     */
+    public void setFieldSeparatorAtEnd(boolean fieldSeparatorAtEnd) {
+        super.setFieldSeparatorAtEnd(fieldSeparatorAtEnd);
+    }
+
+    //---------------------------------------------------------------------
+    
+    /**
+     * Gets the text to output when null found.
+     *
+     * @return the current text to output when null found
+     */
+    public String getNullText() {
+        return super.getNullText();
+    }
+
+    /**
+     * Sets the text to output when null found.
+     *
+     * null is accepted, but will be converted
+     * to an empty String.
+     *
+     * @param nullText  the new text to output when null found
+     */
+    public void setNullText(String nullText) {
+        super.setNullText(nullText);
+    }
+
+    //---------------------------------------------------------------------
+    
+    /**
+     * Gets the text to output when a Collection,
+     * Map or Array size is output.
+     *
+     * This is output before the size value.
+     *
+     * @return the current start of size text
+     */
+    public String getSizeStartText() {
+        return super.getSizeStartText();
+    }
+
+    /**
+     * Sets the start text to output when a Collection,
+     * Map or Array size is output.
+     *
+     * This is output before the size value.
+     *
+     * null is accepted, but will be converted to
+     * an empty String.
+     *
+     * @param sizeStartText  the new start of size text
+     */
+    public void setSizeStartText(String sizeStartText) {
+        super.setSizeStartText(sizeStartText);
+    }
+
+    //---------------------------------------------------------------------
+    
+    /**
+     * Gets the end text to output when a Collection,
+     * Map or Array size is output.
+     *
+     * This is output after the size value.
+     *
+     * @return the current end of size text
+     */
+    public String getSizeEndText() {
+        return super.getSizeEndText();
+    }
+
+    /**
+     * Sets the end text to output when a Collection,
+     * Map or Array size is output.
+     *
+     * This is output after the size value.
+     *
+     * null is accepted, but will be converted
+     * to an empty String.
+     *
+     * @param sizeEndText  the new end of size text
+     */
+    public void setSizeEndText(String sizeEndText) {
+        super.setSizeEndText(sizeEndText);
+    }
+
+    //---------------------------------------------------------------------
+    
+    /**
+     * Gets the start text to output when an Object is
+     * output in summary mode.
+     *
+     * This is output before the size value.
+     *
+     * @return the current start of summary text
+     */
+    public String getSummaryObjectStartText() {
+        return super.getSummaryObjectStartText();
+    }
+
+    /**
+     * Sets the start text to output when an Object is
+     * output in summary mode.
+     *
+     * This is output before the size value.
+     *
+     * null is accepted, but will be converted to
+     * an empty String.
+     *
+     * @param summaryObjectStartText  the new start of summary text
+     */
+    public void setSummaryObjectStartText(String summaryObjectStartText) {
+        super.setSummaryObjectStartText(summaryObjectStartText);
+    }
+
+    //---------------------------------------------------------------------
+    
+    /**
+     * Gets the end text to output when an Object is
+     * output in summary mode.
+     *
+     * This is output after the size value.
+     *
+     * @return the current end of summary text
+     */
+    public String getSummaryObjectEndText() {
+        return super.getSummaryObjectEndText();
+    }
+
+    /**
+     * Sets the end text to output when an Object is
+     * output in summary mode.
+     *
+     * This is output after the size value.
+     *
+     * null is accepted, but will be converted to
+     * an empty String.
+     *
+     * @param summaryObjectEndText  the new end of summary text
+     */
+    public void setSummaryObjectEndText(String summaryObjectEndText) {
+        super.setSummaryObjectEndText(summaryObjectEndText);
+    }
+
+    //---------------------------------------------------------------------
+    
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/ToStringBuilder.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/builder/ToStringBuilder.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/ToStringBuilder.java	30 Aug 2012 16:24:43 -0000	1.1
@@ -0,0 +1,1082 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang.builder;
+
+import org.apache.commons.lang.BooleanUtils;
+import org.apache.commons.lang.ObjectUtils;
+
+/**
+ * Assists in implementing {@link Object#toString()} methods.
+ *
+ * This class enables a good and consistent toString() to be built for any
+ * class or object. This class aims to simplify the process by:
+ * 
+ *  - allowing field names
 
+ *  - handling all types consistently
 
+ *  - handling nulls consistently
 
+ *  - outputting arrays and multi-dimensional arrays
 
+ *  - enabling the detail level to be controlled for Objects and Collections
 
+ *  - handling class hierarchies
 
+ * 
+ *
+ * To use this class write code as follows:
+ *
+ * 
+ * public class Person {
+ *   String name;
+ *   int age;
+ *   boolean isSmoker;
+ * 
+ *   ...
+ * 
+ *   public String toString() {
+ *     return new ToStringBuilder(this).
+ *       append("name", name).
+ *       append("age", age).
+ *       append("smoker", smoker).
+ *       toString();
+ *   }
+ * }
+ * 
+ *
+ * This will produce a toString of the format:
+ * Person@7f54[name=Stephen,age=29,smoker=false]
+ * 
+ * To add the superclass toString, use {@link #appendSuper}.
+ * To append the toString from an object that is delegated
+ * to (or any other object), use {@link #appendToString}.
+ *
+ * Alternatively, there is a method that uses reflection to determine
+ * the fields to test. Because these fields are usually private, the method, 
+ * reflectionToString, uses AccessibleObject.setAccessible to
+ * change the visibility of the fields. This will fail under a security manager,
+ * unless the appropriate permissions are set up correctly. It is also
+ * slower than testing explicitly.
+ *
+ * A typical invocation for this method would look like:
+ *
+ * 
+ * public String toString() {
+ *   return ToStringBuilder.reflectionToString(this);
+ * }
+ * 
+ *
+ * You can also use the builder to debug 3rd party objects:
+ *
+ * 
+ * System.out.println("An object: " + ToStringBuilder.reflectionToString(anObject));
+ * 
+ * 
+ * The exact format of the toString is determined by
+ * the {@link ToStringStyle} passed into the constructor.
+ *
+ * @author Stephen Colebourne
+ * @author Gary Gregory
+ * @author Pete Gieser
+ * @since 1.0
+ * @version $Id: ToStringBuilder.java,v 1.1 2012/08/30 16:24:43 marcin Exp $
+ */
+public class ToStringBuilder {
+
+    /**
+     * The default style of output to use.
+     */
+    private static ToStringStyle defaultStyle = ToStringStyle.DEFAULT_STYLE;
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Gets the default ToStringStyle to use.
+     *
+     * This could allow the ToStringStyle to be
+     * controlled for an entire application with one call.
+     *
+     * This might be used to have a verbose
+     * ToStringStyle during development and a compact
+     * ToStringStyle in production.
+     * 
+     * @return the default ToStringStyle
+     */
+    public static ToStringStyle getDefaultStyle() {
+        return defaultStyle;
+    }
+
+    /**
+     * Forwards to ReflectionToStringBuilder.
+     * 
+     * @see ReflectionToStringBuilder#toString(Object)
+     */
+    public static String reflectionToString(Object object) {
+        return ReflectionToStringBuilder.toString(object);
+    }
+
+    /**
+     * Forwards to ReflectionToStringBuilder.
+     * 
+     * @see ReflectionToStringBuilder#toString(Object,ToStringStyle)
+     */
+    public static String reflectionToString(Object object, ToStringStyle style) {
+        return ReflectionToStringBuilder.toString(object, style);
+    }
+
+    /**
+     * Forwards to ReflectionToStringBuilder.
+     * 
+     * @see ReflectionToStringBuilder#toString(Object,ToStringStyle,boolean)
+     */
+    public static String reflectionToString(Object object, ToStringStyle style, boolean outputTransients) {
+        return ReflectionToStringBuilder.toString(object, style, outputTransients, null);
+    }
+
+    /**
+     * Forwards to ReflectionToStringBuilder.
+     * 
+     * @see ReflectionToStringBuilder#toString(Object,ToStringStyle,boolean,Class)
+     * @since 2.0
+     */
+    public static String reflectionToString(
+        Object object,
+        ToStringStyle style,
+        boolean outputTransients,
+        Class reflectUpToClass) {
+        return ReflectionToStringBuilder.toString(object, style, outputTransients, reflectUpToClass);
+    }
+
+    /**
+     * Sets the default ToStringStyle to use.
+     * 
+     * @param style  the default ToStringStyle
+     * @throws IllegalArgumentException if the style is null
+     */
+    public static void setDefaultStyle(ToStringStyle style) {
+        if (style == null) {
+            throw new IllegalArgumentException("The style must not be null");
+        }
+        defaultStyle = style;
+    }
+
+    /**
+     * Current toString buffer.
+     */
+    private final StringBuffer buffer;
+
+    /**
+     * The object being output.
+     */
+    private final Object object;
+
+    /**
+     * The style of output to use.
+     */
+    private final ToStringStyle style;
+
+    /**
+     * Constructor for ToStringBuilder.
+     *
+     * This constructor outputs using the default style set with
+     * setDefaultStyle.
+     * 
+     * @param object  the Object to build a toString for,
+     *  must not be null
+     * @throws IllegalArgumentException  if the Object passed in is
+     *  null
+     */
+    public ToStringBuilder(Object object) {
+        this(object, getDefaultStyle(), null);
+    }
+
+    /**
+     * Constructor for ToStringBuilder specifying the
+     * output style.
+     *
+     * If the style is null, the default style is used.
+     * 
+     * @param object  the Object to build a toString for,
+     *  must not be null
+     * @param style  the style of the toString to create,
+     *  may be null
+     * @throws IllegalArgumentException  if the Object passed in is
+     *  null
+     */
+    public ToStringBuilder(Object object, ToStringStyle style) {
+        this(object, style, null);
+    }
+
+    /**
+     * Constructor for ToStringBuilder.
+     *
+     * If the style is null, the default style is used.
+     *
+     * If the buffer is null, a new one is created.
+     * 
+     * @param object  the Object to build a toString for,
+     *  must not be null
+     * @param style  the style of the toString to create,
+     *  may be null
+     * @param buffer  the StringBuffer to populate, may be
+     *  null
+     * @throws IllegalArgumentException  if the Object passed in is
+     *  null
+     */
+    public ToStringBuilder(Object object, ToStringStyle style, StringBuffer buffer) {
+        super();
+        if (object == null) {
+            throw new IllegalArgumentException("The object to create a toString for must not be null");
+        }
+        if (style == null) {
+            style = getDefaultStyle();
+        }
+        if (buffer == null) {
+            buffer = new StringBuffer(512);
+        }
+        this.buffer = buffer;
+        this.style = style;
+        this.object = object;
+
+        style.appendStart(buffer, object);
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Append to the toString a boolean
+     * value.
+     *
+     * @param value  the value to add to the toString
+     * @return this
+     */
+    public ToStringBuilder append(boolean value) {
+        style.append(buffer, null, value);
+        return this;
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Append to the toString a boolean
+     * array.
+     *
+     * @param array  the array to add to the toString
+     * @return this
+     */
+    public ToStringBuilder append(boolean[] array) {
+        style.append(buffer, null, array, null);
+        return this;
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Append to the toString a byte
+     * value.
+     *
+     * @param value  the value to add to the toString
+     * @return this
+     */
+    public ToStringBuilder append(byte value) {
+        style.append(buffer, null, value);
+        return this;
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Append to the toString a byte
+     * array.
+     *
+     * @param array  the array to add to the toString
+     * @return this
+     */
+    public ToStringBuilder append(byte[] array) {
+        style.append(buffer, null, array, null);
+        return this;
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Append to the toString a char
+     * value.
+     *
+     * @param value  the value to add to the toString
+     * @return this
+     */
+    public ToStringBuilder append(char value) {
+        style.append(buffer, null, value);
+        return this;
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Append to the toString a char
+     * array.
+     *
+     * @param array  the array to add to the toString
+     * @return this
+     */
+    public ToStringBuilder append(char[] array) {
+        style.append(buffer, null, array, null);
+        return this;
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Append to the toString a double
+     * value.
+     *
+     * @param value  the value to add to the toString
+     * @return this
+     */
+    public ToStringBuilder append(double value) {
+        style.append(buffer, null, value);
+        return this;
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Append to the toString a double
+     * array.
+     *
+     * @param array  the array to add to the toString
+     * @return this
+     */
+    public ToStringBuilder append(double[] array) {
+        style.append(buffer, null, array, null);
+        return this;
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Append to the toString a float
+     * value.
+     *
+     * @param value  the value to add to the toString
+     * @return this
+     */
+    public ToStringBuilder append(float value) {
+        style.append(buffer, null, value);
+        return this;
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Append to the toString a float
+     * array.
+     *
+     * @param array  the array to add to the toString
+     * @return this
+     */
+    public ToStringBuilder append(float[] array) {
+        style.append(buffer, null, array, null);
+        return this;
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Append to the toString an int
+     * value.
+     *
+     * @param value  the value to add to the toString
+     * @return this
+     */
+    public ToStringBuilder append(int value) {
+        style.append(buffer, null, value);
+        return this;
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Append to the toString an int
+     * array.
+     *
+     * @param array  the array to add to the toString
+     * @return this
+     */
+    public ToStringBuilder append(int[] array) {
+        style.append(buffer, null, array, null);
+        return this;
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Append to the toString a long
+     * value.
+     *
+     * @param value  the value to add to the toString
+     * @return this
+     */
+    public ToStringBuilder append(long value) {
+        style.append(buffer, null, value);
+        return this;
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Append to the toString a long
+     * array.
+     *
+     * @param array  the array to add to the toString
+     * @return this
+     */
+    public ToStringBuilder append(long[] array) {
+        style.append(buffer, null, array, null);
+        return this;
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Append to the toString an Object
+     * value.
+     *
+     * @param object  the value to add to the toString
+     * @return this
+     */
+    public ToStringBuilder append(Object object) {
+        style.append(buffer, null, object, null);
+        return this;
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Append to the toString an Object
+     * array.
+     *
+     * @param array  the array to add to the toString
+     * @return this
+     */
+    public ToStringBuilder append(Object[] array) {
+        style.append(buffer, null, array, null);
+        return this;
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Append to the toString a short
+     * value.
+     *
+     * @param value  the value to add to the toString
+     * @return this
+     */
+    public ToStringBuilder append(short value) {
+        style.append(buffer, null, value);
+        return this;
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Append to the toString a short
+     * array.
+     *
+     * @param array  the array to add to the toString
+     * @return this
+     */
+    public ToStringBuilder append(short[] array) {
+        style.append(buffer, null, array, null);
+        return this;
+    }
+
+    /**
+     * Append to the toString a boolean
+     * value.
+     *
+     * @param fieldName  the field name
+     * @param value  the value to add to the toString
+     * @return this
+     */
+    public ToStringBuilder append(String fieldName, boolean value) {
+        style.append(buffer, fieldName, value);
+        return this;
+    }
+
+    /**
+     * Append to the toString a boolean
+     * array.
+     *
+     * @param fieldName  the field name
+     * @param array  the array to add to the hashCode
+     * @return this
+     */
+    public ToStringBuilder append(String fieldName, boolean[] array) {
+        style.append(buffer, fieldName, array, null);
+        return this;
+    }
+
+    /**
+     * Append to the toString a boolean
+     * array.
+     *
+     * A boolean parameter controls the level of detail to show.
+     * Setting true will output the array in full. Setting
+     * false will output a summary, typically the size of
+     * the array.
+     *
+     * @param fieldName  the field name
+     * @param array  the array to add to the toString
+     * @param fullDetail  true for detail, false
+     *  for summary info
+     * @return this
+     */
+    public ToStringBuilder append(String fieldName, boolean[] array, boolean fullDetail) {
+        style.append(buffer, fieldName, array, BooleanUtils.toBooleanObject(fullDetail));
+        return this;
+    }
+
+    /**
+     * Append to the toString an byte
+     * value.
+     *
+     * @param fieldName  the field name
+     * @param value  the value to add to the toString
+     * @return this
+     */
+    public ToStringBuilder append(String fieldName, byte value) {
+        style.append(buffer, fieldName, value);
+        return this;
+    }
+
+    /**
+     * Append to the toString a byte array.
+     *
+     * @param fieldName  the field name
+     * @param array  the array to add to the toString
+     * @return this
+     */
+    public ToStringBuilder append(String fieldName, byte[] array) {
+        style.append(buffer, fieldName, array, null);
+        return this;
+    }
+
+    /**
+     * Append to the toString a byte
+     * array.
+     *
+     * A boolean parameter controls the level of detail to show.
+     * Setting true will output the array in full. Setting
+     * false will output a summary, typically the size of
+     * the array.
+     *
+     * @param fieldName  the field name
+     * @param array  the array to add to the toString
+     * @param fullDetail  true for detail, false
+     *  for summary info
+     * @return this
+     */
+    public ToStringBuilder append(String fieldName, byte[] array, boolean fullDetail) {
+        style.append(buffer, fieldName, array, BooleanUtils.toBooleanObject(fullDetail));
+        return this;
+    }
+
+    /**
+     * 
Append to the toString a char
+     * value.
+     *
+     * @param fieldName  the field name
+     * @param value  the value to add to the toString
+     * @return this
+     */
+    public ToStringBuilder append(String fieldName, char value) {
+        style.append(buffer, fieldName, value);
+        return this;
+    }
+
+    /**
+     * Append to the toString a char
+     * array.
+     *
+     * @param fieldName  the field name
+     * @param array  the array to add to the toString
+     * @return this
+     */
+    public ToStringBuilder append(String fieldName, char[] array) {
+        style.append(buffer, fieldName, array, null);
+        return this;
+    }
+
+    /**
+     * Append to the toString a char
+     * array.
+     *
+     * A boolean parameter controls the level of detail to show.
+     * Setting true will output the array in full. Setting
+     * false will output a summary, typically the size of
+     * the array.
+     *
+     * @param fieldName  the field name
+     * @param array  the array to add to the toString
+     * @param fullDetail  true for detail, false
+     *  for summary info
+     * @return this
+     */
+    public ToStringBuilder append(String fieldName, char[] array, boolean fullDetail) {
+        style.append(buffer, fieldName, array, BooleanUtils.toBooleanObject(fullDetail));
+        return this;
+    }
+
+    /**
+     * Append to the toString a double
+     * value.
+     *
+     * @param fieldName  the field name
+     * @param value  the value to add to the toString
+     * @return this
+     */
+    public ToStringBuilder append(String fieldName, double value) {
+        style.append(buffer, fieldName, value);
+        return this;
+    }
+
+    /**
+     * Append to the toString a double
+     * array.
+     *
+     * @param fieldName  the field name
+     * @param array  the array to add to the toString
+     * @return this
+     */
+    public ToStringBuilder append(String fieldName, double[] array) {
+        style.append(buffer, fieldName, array, null);
+        return this;
+    }
+
+    /**
+     * Append to the toString a double
+     * array.
+     *
+     * A boolean parameter controls the level of detail to show.
+     * Setting true will output the array in full. Setting
+     * false will output a summary, typically the size of
+     * the array.
+     *
+     * @param fieldName  the field name
+     * @param array  the array to add to the toString
+     * @param fullDetail  true for detail, false
+     *  for summary info
+     * @return this
+     */
+    public ToStringBuilder append(String fieldName, double[] array, boolean fullDetail) {
+        style.append(buffer, fieldName, array, BooleanUtils.toBooleanObject(fullDetail));
+        return this;
+    }
+
+    /**
+     * Append to the toString an float
+     * value.
+     *
+     * @param fieldName  the field name
+     * @param value  the value to add to the toString
+     * @return this
+     */
+    public ToStringBuilder append(String fieldName, float value) {
+        style.append(buffer, fieldName, value);
+        return this;
+    }
+
+    /**
+     * Append to the toString a float
+     * array.
+     *
+     * @param fieldName  the field name
+     * @param array  the array to add to the toString
+     * @return this
+     */
+    public ToStringBuilder append(String fieldName, float[] array) {
+        style.append(buffer, fieldName, array, null);
+        return this;
+    }
+
+    /**
+     * Append to the toString a float
+     * array.
+     *
+     * A boolean parameter controls the level of detail to show.
+     * Setting true will output the array in full. Setting
+     * false will output a summary, typically the size of
+     * the array.
+     *
+     * @param fieldName  the field name
+     * @param array  the array to add to the toString
+     * @param fullDetail  true for detail, false
+     *  for summary info
+     * @return this
+     */
+    public ToStringBuilder append(String fieldName, float[] array, boolean fullDetail) {
+        style.append(buffer, fieldName, array, BooleanUtils.toBooleanObject(fullDetail));
+        return this;
+    }
+
+    /**
+     * Append to the toString an int
+     * value.
+     *
+     * @param fieldName  the field name
+     * @param value  the value to add to the toString
+     * @return this
+     */
+    public ToStringBuilder append(String fieldName, int value) {
+        style.append(buffer, fieldName, value);
+        return this;
+    }
+
+    /**
+     * Append to the toString an int
+     * array.
+     *
+     * @param fieldName  the field name
+     * @param array  the array to add to the toString
+     * @return this
+     */
+    public ToStringBuilder append(String fieldName, int[] array) {
+        style.append(buffer, fieldName, array, null);
+        return this;
+    }
+
+    /**
+     * Append to the toString an int
+     * array.
+     *
+     * A boolean parameter controls the level of detail to show.
+     * Setting true will output the array in full. Setting
+     * false will output a summary, typically the size of
+     * the array.
+     *
+     * @param fieldName  the field name
+     * @param array  the array to add to the toString
+     * @param fullDetail  true for detail, false
+     *  for summary info
+     * @return this
+     */
+    public ToStringBuilder append(String fieldName, int[] array, boolean fullDetail) {
+        style.append(buffer, fieldName, array, BooleanUtils.toBooleanObject(fullDetail));
+        return this;
+    }
+
+    /**
+     * Append to the toString a long
+     * value.
+     *
+     * @param fieldName  the field name
+     * @param value  the value to add to the toString
+     * @return this
+     */
+    public ToStringBuilder append(String fieldName, long value) {
+        style.append(buffer, fieldName, value);
+        return this;
+    }
+
+    /**
+     * Append to the toString a long
+     * array.
+     *
+     * @param fieldName  the field name
+     * @param array  the array to add to the toString
+     * @return this
+     */
+    public ToStringBuilder append(String fieldName, long[] array) {
+        style.append(buffer, fieldName, array, null);
+        return this;
+    }
+
+    /**
+     * Append to the toString a long
+     * array.
+     *
+     * A boolean parameter controls the level of detail to show.
+     * Setting true will output the array in full. Setting
+     * false will output a summary, typically the size of
+     * the array.
+     *
+     * @param fieldName  the field name
+     * @param array  the array to add to the toString
+     * @param fullDetail  true for detail, false
+     *  for summary info
+     * @return this
+     */
+    public ToStringBuilder append(String fieldName, long[] array, boolean fullDetail) {
+        style.append(buffer, fieldName, array, BooleanUtils.toBooleanObject(fullDetail));
+        return this;
+    }
+
+    /**
+     * Append to the toString an Object
+     * value.
+     *
+     * @param fieldName  the field name
+     * @param object  the value to add to the toString
+     * @return this
+     */
+    public ToStringBuilder append(String fieldName, Object object) {
+        style.append(buffer, fieldName, object, null);
+        return this;
+    }
+
+    /**
+     * Append to the toString an Object
+     * value.
+     *
+     * @param fieldName  the field name
+     * @param object  the value to add to the toString
+     * @param fullDetail  true for detail,
+     *  false for summary info
+     * @return this
+     */
+    public ToStringBuilder append(String fieldName, Object object, boolean fullDetail) {
+        style.append(buffer, fieldName, object, BooleanUtils.toBooleanObject(fullDetail));
+        return this;
+    }
+
+    /**
+     * Append to the toString an Object
+     * array.
+     *
+     * @param fieldName  the field name
+     * @param array  the array to add to the toString
+     * @return this
+     */
+    public ToStringBuilder append(String fieldName, Object[] array) {
+        style.append(buffer, fieldName, array, null);
+        return this;
+    }
+
+    /**
+     * Append to the toString an Object
+     * array.
+     *
+     * A boolean parameter controls the level of detail to show.
+     * Setting true will output the array in full. Setting
+     * false will output a summary, typically the size of
+     * the array.
+     *
+     * @param fieldName  the field name
+     * @param array  the array to add to the toString
+     * @param fullDetail  true for detail, false
+     *  for summary info
+     * @return this
+     */
+    public ToStringBuilder append(String fieldName, Object[] array, boolean fullDetail) {
+        style.append(buffer, fieldName, array, BooleanUtils.toBooleanObject(fullDetail));
+        return this;
+    }
+
+    /**
+     * Append to the toString an short
+     * value.
+     *
+     * @param fieldName  the field name
+     * @param value  the value to add to the toString
+     * @return this
+     */
+    public ToStringBuilder append(String fieldName, short value) {
+        style.append(buffer, fieldName, value);
+        return this;
+    }
+
+    /**
+     * Append to the toString a short
+     * array.
+     *
+     * @param fieldName  the field name
+     * @param array  the array to add to the toString
+     * @return this
+     */
+    public ToStringBuilder append(String fieldName, short[] array) {
+        style.append(buffer, fieldName, array, null);
+        return this;
+    }
+
+    /**
+     * Append to the toString a short
+     * array.
+     *
+     * A boolean parameter controls the level of detail to show.
+     * Setting true will output the array in full. Setting
+     * false will output a summary, typically the size of
+     * the array.
+     *
+     * @param fieldName  the field name
+     * @param array  the array to add to the toString
+     * @param fullDetail  true for detail, false
+     *  for summary info
+     * @return this
+     */
+    public ToStringBuilder append(String fieldName, short[] array, boolean fullDetail) {
+        style.append(buffer, fieldName, array, BooleanUtils.toBooleanObject(fullDetail));
+        return this;
+    }
+
+    /**
+     * 
Appends with the same format as the default Object toString()
+     *  method. Appends the class name followed by 
+     * {@link System#identityHashCode(java.lang.Object)}.
+     * 
+     * @param object  the Object whose class name and id to output
+     * @since 2.0
+     */
+    public ToStringBuilder appendAsObjectToString(Object object) {
+        ObjectUtils.appendIdentityToString(this.getStringBuffer(), object);
+        return this;
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Append the toString from the superclass.
+     * 
+     * This method assumes that the superclass uses the same ToStringStyle
+     * as this one.
+     * 
+     * If superToString is null, no change is made.
+     *
+     * @param superToString  the result of super.toString()
+     * @return this
+     * @since 2.0
+     */
+    public ToStringBuilder appendSuper(String superToString) {
+        if (superToString != null) {
+            style.appendSuper(buffer, superToString);
+        }
+        return this;
+    }
+
+    /**
+     * Append the toString from another object.
+     * 
+     * This method is useful where a class delegates most of the implementation of
+     * its properties to another class. You can then call toString() on
+     * the other class and pass the result into this method.
+     * 
+     * 
+     *   private AnotherObject delegate;
+     *   private String fieldInThisClass;
+     * 
+     *   public String toString() {
+     *     return new ToStringBuilder(this).
+     *       appendToString(delegate.toString()).
+     *       append(fieldInThisClass).
+     *       toString();
+     *   }
+     * 
+     * This method assumes that the other object uses the same ToStringStyle
+     * as this one.
+     * 
+     * If the toString is null, no change is made.
+     *
+     * @param toString  the result of toString() on another object
+     * @return this
+     * @since 2.0
+     */
+    public ToStringBuilder appendToString(String toString) {
+        if (toString != null) {
+            style.appendToString(buffer, toString);
+        }
+        return this;
+    }
+
+    /**
+     * Gets the StringBuffer being populated.
+     * 
+     * @return the StringBuffer being populated
+     */
+    public StringBuffer getStringBuffer() {
+        return buffer;
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Gets the ToStringStyle being used.
+     * 
+     * @return the ToStringStyle being used
+     * @since 2.0
+     */
+    public ToStringStyle getStyle() {
+        return style;
+    }
+
+    /**
+     * Returns the built toString.
+     * 
+     * This method appends the end of data indicator, and can only be called once.
+     * Use {@link #getStringBuffer} to get the current string state.
+     * 
+     * @return the String toString
+     */
+    public String toString() {
+        style.appendEnd(buffer, object);
+        return buffer.toString();
+    }
+
+    /**
+     * Returns the Object being output.
+     * 
+     * @return The object being output.
+     * @since 2.0
+     */
+    public Object getObject() {
+        return object;
+    }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/ToStringStyle.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/builder/ToStringStyle.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/ToStringStyle.java	30 Aug 2012 16:24:43 -0000	1.1
@@ -0,0 +1,2169 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang.builder;
+
+import java.io.Serializable;
+import java.lang.reflect.Array;
+import java.util.Collection;
+import java.util.Map;
+
+import org.apache.commons.lang.ClassUtils;
+import org.apache.commons.lang.ObjectUtils;
+import org.apache.commons.lang.SystemUtils;
+
+/**
+ * Controls String formatting for {@link ToStringBuilder}.
+ * The main public interface is always via ToStringBuilder.
+ *
+ * These classes are intended to be used as Singletons.
+ * There is no need to instantiate a new style each time. A program
+ * will generally use one of the predefined constants on this class.
+ * Alternatively, the {@link StandardToStringStyle} class can be used
+ * to set the individual settings. Thus most styles can be achieved
+ * without subclassing.
+ *
+ * If required, a subclass can override as many or as few of the
+ * methods as it requires. Each object type (from boolean
+ * to long to Object to int[]) has
+ * its own methods to output it. Most have two versions, detail and summary.
+ *
+ * 
For example, the detail version of the array based methods will
+ * output the whole array, whereas the summary method will just output
+ * the array length.
+ *
+ * @author Stephen Colebourne
+ * @author Gary Gregory
+ * @author Pete Gieser
+ * @since 1.0
+ * @version $Id: ToStringStyle.java,v 1.1 2012/08/30 16:24:43 marcin Exp $
+ */
+public abstract class ToStringStyle implements Serializable {
+
+    /**
+     * The default toString style.
+     */
+    public static final ToStringStyle DEFAULT_STYLE = new DefaultToStringStyle();
+    /**
+     * The multi line toString style.
+     */
+    public static final ToStringStyle MULTI_LINE_STYLE = new MultiLineToStringStyle();
+    /**
+     * The no field names toString style.
+     */
+    public static final ToStringStyle NO_FIELD_NAMES_STYLE = new NoFieldNameToStringStyle();
+    /**
+     * The simple toString style.
+     */
+    public static final ToStringStyle SIMPLE_STYLE = new SimpleToStringStyle();
+
+    /**
+     * Whether to use the field names, the default is true.
+     */
+    private boolean useFieldNames = true;
+    /**
+     * Whether to use the class name, the default is true.
+     */
+    private boolean useClassName = true;
+    /**
+     * Whether to use short class names, the default is false.
+     */
+    private boolean useShortClassName = false;
+    /**
+     * Whether to use the identity hash code, the default is true.
+     */
+    private boolean useIdentityHashCode = true;
+
+    /**
+     * The content start '['.
+     */
+    private String contentStart = "[";
+    /**
+     * The content end ']'.
+     */
+    private String contentEnd = "]";
+    /**
+     * The field name value separator '='.
+     */
+    private String fieldNameValueSeparator = "=";
+    /**
+     * Whether the field separator should be added before any other fields.
+     */
+    private boolean fieldSeparatorAtStart = false;
+    /**
+     * Whether the field separator should be added after any other fields.
+     */
+    private boolean fieldSeparatorAtEnd = false;
+    /**
+     * The field separator ','.
+     */
+    private String fieldSeparator = ",";
+    /**
+     * The array start '{'.
+     */
+    private String arrayStart = "{";
+    /**
+     * The array separator ','.
+     */
+    private String arraySeparator = ",";
+    /**
+     * The detail for array content.
+     */
+    private boolean arrayContentDetail = true;
+    /**
+     * The array end '}'.
+     */
+    private String arrayEnd = "}";
+    /**
+     * The value to use when fullDetail is null,
+     * the default value is true.
+     */
+    private boolean defaultFullDetail = true;
+    /**
+     * The null text '<null>'.
+     */
+    private String nullText = "";
+    /**
+     * The summary size text start '.
+     */
+    private String sizeStartText = "'>'  .
+     */
+    private String sizeEndText = ">";
+    /**
+     * The summary object text start '<'.
+     */
+    private String summaryObjectStartText = "<";
+    /**
+     * The summary object text start '>'.
+     */
+    private String summaryObjectEndText = ">";
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Constructor.
+     */
+    protected ToStringStyle() {
+        super();
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Append to the toString the superclass toString.
+     * 
+     * A null superToString is ignored.
+     * 
+     * @param buffer  the StringBuffer to populate
+     * @param superToString  the super.toString()
+     * @since 2.0
+     */
+    public void appendSuper(StringBuffer buffer, String superToString) {
+        appendToString(buffer, superToString);
+    }
+
+    /**
+     * Append to the toString another toString.
+     * 
+     * A null toString is ignored.
+     * 
+     * @param buffer  the StringBuffer to populate
+     * @param toString  the additional toString
+     * @since 2.0
+     */
+    public void appendToString(StringBuffer buffer, String toString) {
+        if (toString != null) {
+            int pos1 = toString.indexOf(contentStart) + contentStart.length();
+            int pos2 = toString.lastIndexOf(contentEnd);
+            if (pos1 != pos2 && pos1 >= 0 && pos2 >= 0) {
+                String data = toString.substring(pos1, pos2);
+                if (fieldSeparatorAtStart) {
+                    removeLastFieldSeparator(buffer);
+                }
+                buffer.append(data);
+                appendFieldSeparator(buffer);
+            }
+        }
+    }
+
+    /**
+     * Append to the toString the start of data indicator.
+     * 
+     * @param buffer  the StringBuffer to populate
+     * @param object  the Object to build a
+     *  toString for, must not be null
+     */
+    public void appendStart(StringBuffer buffer, Object object) {
+        appendClassName(buffer, object);
+        appendIdentityHashCode(buffer, object);
+        appendContentStart(buffer);
+        if (fieldSeparatorAtStart) {
+            appendFieldSeparator(buffer);
+        }
+    }
+
+    /**
+     * Append to the toString the end of data indicator.
+     * 
+     * @param buffer  the StringBuffer to populate
+     * @param object  the Object to build a
+     *  toString for, must not be null
+     */
+    public void appendEnd(StringBuffer buffer, Object object) {
+        if (fieldSeparatorAtEnd == false) {
+            removeLastFieldSeparator(buffer);
+        }
+        appendContentEnd(buffer);
+    }
+
+    /**
+     * Remove the last field separator from the buffer.
+     * 
+     * @param buffer  the StringBuffer to populate
+     * @since 2.0
+     */
+    protected void removeLastFieldSeparator(StringBuffer buffer) {
+        int len = buffer.length();
+        int sepLen = fieldSeparator.length();
+        if (len > 0 && sepLen > 0 && len >= sepLen) {
+            boolean match = true;
+            for (int i = 0; i < sepLen; i++) {
+                if (buffer.charAt(len - 1 - i) != fieldSeparator.charAt(sepLen - 1 - i)) {
+                    match = false;
+                    break;
+                }
+            }
+            if (match) {
+                buffer.setLength(len - sepLen);
+            }
+        }
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Append to the toString an Object
+     * value, printing the full toString of the
+     * Object passed in.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name
+     * @param value  the value to add to the toString
+     * @param fullDetail  true for detail, false
+     *  for summary info, null for style decides
+     */
+    public void append(StringBuffer buffer, String fieldName, Object value, Boolean fullDetail) {
+        appendFieldStart(buffer, fieldName);
+
+        if (value == null) {
+            appendNullText(buffer, fieldName);
+
+        } else {
+            appendInternal(buffer, fieldName, value, isFullDetail(fullDetail));
+        }
+
+        appendFieldEnd(buffer, fieldName);
+    }
+
+    /**
+     * Append to the toString an Object,
+     * correctly interpreting its type.
+     *
+     * This method performs the main lookup by Class type to correctly
+     * route arrays, Collections, Maps and
+     * Objects to the appropriate method.
+     *
+     * Either detail or summary views can be specified.
+     *
+     * If a cycle is detected, an object will be appended with the
+     * Object.toString() format.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name, typically not used as already appended
+     * @param value  the value to add to the toString,
+     *  not null
+     * @param detail  output detail or not
+     */
+    protected void appendInternal(StringBuffer buffer, String fieldName, Object value, boolean detail) {
+        if (ReflectionToStringBuilder.isRegistered(value)
+            && !(value instanceof Number || value instanceof Boolean || value instanceof Character)) {
+            ObjectUtils.appendIdentityToString(buffer, value);
+
+        } else if (value instanceof Collection) {
+            if (detail) {
+                appendDetail(buffer, fieldName, (Collection) value);
+            } else {
+                appendSummarySize(buffer, fieldName, ((Collection) value).size());
+            }
+
+        } else if (value instanceof Map) {
+            if (detail) {
+                appendDetail(buffer, fieldName, (Map) value);
+            } else {
+                appendSummarySize(buffer, fieldName, ((Map) value).size());
+            }
+
+        } else if (value instanceof long[]) {
+            if (detail) {
+                appendDetail(buffer, fieldName, (long[]) value);
+            } else {
+                appendSummary(buffer, fieldName, (long[]) value);
+            }
+
+        } else if (value instanceof int[]) {
+            if (detail) {
+                appendDetail(buffer, fieldName, (int[]) value);
+            } else {
+                appendSummary(buffer, fieldName, (int[]) value);
+            }
+
+        } else if (value instanceof short[]) {
+            if (detail) {
+                appendDetail(buffer, fieldName, (short[]) value);
+            } else {
+                appendSummary(buffer, fieldName, (short[]) value);
+            }
+
+        } else if (value instanceof byte[]) {
+            if (detail) {
+                appendDetail(buffer, fieldName, (byte[]) value);
+            } else {
+                appendSummary(buffer, fieldName, (byte[]) value);
+            }
+
+        } else if (value instanceof char[]) {
+            if (detail) {
+                appendDetail(buffer, fieldName, (char[]) value);
+            } else {
+                appendSummary(buffer, fieldName, (char[]) value);
+            }
+
+        } else if (value instanceof double[]) {
+            if (detail) {
+                appendDetail(buffer, fieldName, (double[]) value);
+            } else {
+                appendSummary(buffer, fieldName, (double[]) value);
+            }
+
+        } else if (value instanceof float[]) {
+            if (detail) {
+                appendDetail(buffer, fieldName, (float[]) value);
+            } else {
+                appendSummary(buffer, fieldName, (float[]) value);
+            }
+
+        } else if (value instanceof boolean[]) {
+            if (detail) {
+                appendDetail(buffer, fieldName, (boolean[]) value);
+            } else {
+                appendSummary(buffer, fieldName, (boolean[]) value);
+            }
+
+        } else if (value.getClass().isArray()) {
+            if (detail) {
+                appendDetail(buffer, fieldName, (Object[]) value);
+            } else {
+                appendSummary(buffer, fieldName, (Object[]) value);
+            }
+
+        } else {
+            if (detail) {
+                appendDetail(buffer, fieldName, value);
+            } else {
+                appendSummary(buffer, fieldName, value);
+            }
+        }
+    }
+
+    /**
+     * Append to the toString an Object
+     * value, printing the full detail of the Object.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name, typically not used as already appended
+     * @param value  the value to add to the toString,
+     *  not null
+     */
+    protected void appendDetail(StringBuffer buffer, String fieldName, Object value) {
+        buffer.append(value);
+    }
+
+    /**
+     * Append to the toString a Collection.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name, typically not used as already appended
+     * @param coll  the Collection to add to the
+     *  toString, not null
+     */
+    protected void appendDetail(StringBuffer buffer, String fieldName, Collection coll) {
+        buffer.append(coll);
+    }
+
+    /**
+     * Append to the toString a Map.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name, typically not used as already appended
+     * @param map  the Map to add to the toString,
+     *  not null
+     */
+    protected void appendDetail(StringBuffer buffer, String fieldName, Map map) {
+        buffer.append(map);
+    }
+
+    /**
+     * Append to the toString an Object
+     * value, printing a summary of the Object.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name, typically not used as already appended
+     * @param value  the value to add to the toString,
+     *  not null
+     */
+    protected void appendSummary(StringBuffer buffer, String fieldName, Object value) {
+        buffer.append(summaryObjectStartText);
+        buffer.append(getShortClassName(value.getClass()));
+        buffer.append(summaryObjectEndText);
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Append to the toString a long
+     * value.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name
+     * @param value  the value to add to the toString
+     */
+    public void append(StringBuffer buffer, String fieldName, long value) {
+        appendFieldStart(buffer, fieldName);
+        appendDetail(buffer, fieldName, value);
+        appendFieldEnd(buffer, fieldName);
+    }
+
+    /**
+     * Append to the toString a long
+     * value.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name, typically not used as already appended
+     * @param value  the value to add to the toString
+     */
+    protected void appendDetail(StringBuffer buffer, String fieldName, long value) {
+        buffer.append(value);
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Append to the toString an int
+     * value.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name
+     * @param value  the value to add to the toString
+     */
+    public void append(StringBuffer buffer, String fieldName, int value) {
+        appendFieldStart(buffer, fieldName);
+        appendDetail(buffer, fieldName, value);
+        appendFieldEnd(buffer, fieldName);
+    }
+
+    /**
+     * Append to the toString an int
+     * value.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name, typically not used as already appended
+     * @param value  the value to add to the toString
+     */
+    protected void appendDetail(StringBuffer buffer, String fieldName, int value) {
+        buffer.append(value);
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Append to the toString a short
+     * value.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name
+     * @param value  the value to add to the toString
+     */
+    public void append(StringBuffer buffer, String fieldName, short value) {
+        appendFieldStart(buffer, fieldName);
+        appendDetail(buffer, fieldName, value);
+        appendFieldEnd(buffer, fieldName);
+    }
+
+    /**
+     * Append to the toString a short
+     * value.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name, typically not used as already appended
+     * @param value  the value to add to the toString
+     */
+    protected void appendDetail(StringBuffer buffer, String fieldName, short value) {
+        buffer.append(value);
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Append to the toString a byte
+     * value.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name
+     * @param value  the value to add to the toString
+     */
+    public void append(StringBuffer buffer, String fieldName, byte value) {
+        appendFieldStart(buffer, fieldName);
+        appendDetail(buffer, fieldName, value);
+        appendFieldEnd(buffer, fieldName);
+    }
+
+    /**
+     * Append to the toString a byte
+     * value.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name, typically not used as already appended
+     * @param value  the value to add to the toString
+     */
+    protected void appendDetail(StringBuffer buffer, String fieldName, byte value) {
+        buffer.append(value);
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Append to the toString a char
+     * value.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name
+     * @param value  the value to add to the toString
+     */
+    public void append(StringBuffer buffer, String fieldName, char value) {
+        appendFieldStart(buffer, fieldName);
+        appendDetail(buffer, fieldName, value);
+        appendFieldEnd(buffer, fieldName);
+    }
+
+    /**
+     * Append to the toString a char
+     * value.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name, typically not used as already appended
+     * @param value  the value to add to the toString
+     */
+    protected void appendDetail(StringBuffer buffer, String fieldName, char value) {
+        buffer.append(value);
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Append to the toString a double
+     * value.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name
+     * @param value  the value to add to the toString
+     */
+    public void append(StringBuffer buffer, String fieldName, double value) {
+        appendFieldStart(buffer, fieldName);
+        appendDetail(buffer, fieldName, value);
+        appendFieldEnd(buffer, fieldName);
+    }
+
+    /**
+     * Append to the toString a double
+     * value.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name, typically not used as already appended
+     * @param value  the value to add to the toString
+     */
+    protected void appendDetail(StringBuffer buffer, String fieldName, double value) {
+        buffer.append(value);
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Append to the toString a float
+     * value.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name
+     * @param value  the value to add to the toString
+     */
+    public void append(StringBuffer buffer, String fieldName, float value) {
+        appendFieldStart(buffer, fieldName);
+        appendDetail(buffer, fieldName, value);
+        appendFieldEnd(buffer, fieldName);
+    }
+
+    /**
+     * Append to the toString a float
+     * value.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name, typically not used as already appended
+     * @param value  the value to add to the toString
+     */
+    protected void appendDetail(StringBuffer buffer, String fieldName, float value) {
+        buffer.append(value);
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Append to the toString a boolean
+     * value.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name
+     * @param value  the value to add to the toString
+     */
+    public void append(StringBuffer buffer, String fieldName, boolean value) {
+        appendFieldStart(buffer, fieldName);
+        appendDetail(buffer, fieldName, value);
+        appendFieldEnd(buffer, fieldName);
+    }
+
+    /**
+     * Append to the toString a boolean
+     * value.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name, typically not used as already appended
+     * @param value  the value to add to the toString
+     */
+    protected void appendDetail(StringBuffer buffer, String fieldName, boolean value) {
+        buffer.append(value);
+    }
+
+    /**
+     * Append to the toString an Object
+     * array.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name
+     * @param array  the array to add to the toString
+     * @param fullDetail  true for detail, false
+     *  for summary info, null for style decides
+     */
+    public void append(StringBuffer buffer, String fieldName, Object[] array, Boolean fullDetail) {
+        appendFieldStart(buffer, fieldName);
+
+        if (array == null) {
+            appendNullText(buffer, fieldName);
+
+        } else if (isFullDetail(fullDetail)) {
+            appendDetail(buffer, fieldName, array);
+
+        } else {
+            appendSummary(buffer, fieldName, array);
+        }
+
+        appendFieldEnd(buffer, fieldName);
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Append to the toString the detail of an
+     * Object array.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name, typically not used as already appended
+     * @param array  the array to add to the toString,
+     *  not null
+     */
+    protected void appendDetail(StringBuffer buffer, String fieldName, Object[] array) {
+        buffer.append(arrayStart);
+        for (int i = 0; i < array.length; i++) {
+            Object item = array[i];
+            if (i > 0) {
+                buffer.append(arraySeparator);
+            }
+            if (item == null) {
+                appendNullText(buffer, fieldName);
+
+            } else {
+                appendInternal(buffer, fieldName, item, arrayContentDetail);
+            }
+        }
+        buffer.append(arrayEnd);
+    }
+
+    /**
+     * Append to the toString the detail of an array type.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name, typically not used as already appended
+     * @param array  the array to add to the toString,
+     *  not null
+     * @since 2.0
+     */
+    protected void reflectionAppendArrayDetail(StringBuffer buffer, String fieldName, Object array) {
+        buffer.append(arrayStart);
+        int length = Array.getLength(array);
+        for (int i = 0; i < length; i++) {
+            Object item = Array.get(array, i);
+            if (i > 0) {
+                buffer.append(arraySeparator);
+            }
+            if (item == null) {
+                appendNullText(buffer, fieldName);
+
+            } else {
+                appendInternal(buffer, fieldName, item, arrayContentDetail);
+            }
+        }
+        buffer.append(arrayEnd);
+    }
+
+    /**
+     * Append to the toString a summary of an
+     * Object array.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name, typically not used as already appended
+     * @param array  the array to add to the toString,
+     *  not null
+     */
+    protected void appendSummary(StringBuffer buffer, String fieldName, Object[] array) {
+        appendSummarySize(buffer, fieldName, array.length);
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Append to the toString a long
+     * array.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name
+     * @param array  the array to add to the toString
+     * @param fullDetail  true for detail, false
+     *  for summary info, null for style decides
+     */
+    public void append(StringBuffer buffer, String fieldName, long[] array, Boolean fullDetail) {
+        appendFieldStart(buffer, fieldName);
+
+        if (array == null) {
+            appendNullText(buffer, fieldName);
+
+        } else if (isFullDetail(fullDetail)) {
+            appendDetail(buffer, fieldName, array);
+
+        } else {
+            appendSummary(buffer, fieldName, array);
+        }
+
+        appendFieldEnd(buffer, fieldName);
+    }
+
+    /**
+     * Append to the toString the detail of a
+     * long array.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name, typically not used as already appended
+     * @param array  the array to add to the toString,
+     *  not null
+     */
+    protected void appendDetail(StringBuffer buffer, String fieldName, long[] array) {
+        buffer.append(arrayStart);
+        for (int i = 0; i < array.length; i++) {
+            if (i > 0) {
+                buffer.append(arraySeparator);
+            }
+            appendDetail(buffer, fieldName, array[i]);
+        }
+        buffer.append(arrayEnd);
+    }
+
+    /**
+     * Append to the toString a summary of a
+     * long array.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name, typically not used as already appended
+     * @param array  the array to add to the toString,
+     *  not null
+     */
+    protected void appendSummary(StringBuffer buffer, String fieldName, long[] array) {
+        appendSummarySize(buffer, fieldName, array.length);
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Append to the toString an int
+     * array.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name
+     * @param array  the array to add to the toString
+     * @param fullDetail  true for detail, false
+     *  for summary info, null for style decides
+     */
+    public void append(StringBuffer buffer, String fieldName, int[] array, Boolean fullDetail) {
+        appendFieldStart(buffer, fieldName);
+
+        if (array == null) {
+            appendNullText(buffer, fieldName);
+
+        } else if (isFullDetail(fullDetail)) {
+            appendDetail(buffer, fieldName, array);
+
+        } else {
+            appendSummary(buffer, fieldName, array);
+        }
+
+        appendFieldEnd(buffer, fieldName);
+    }
+
+    /**
+     * Append to the toString the detail of an
+     * int array.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name, typically not used as already appended
+     * @param array  the array to add to the toString,
+     *  not null
+     */
+    protected void appendDetail(StringBuffer buffer, String fieldName, int[] array) {
+        buffer.append(arrayStart);
+        for (int i = 0; i < array.length; i++) {
+            if (i > 0) {
+                buffer.append(arraySeparator);
+            }
+            appendDetail(buffer, fieldName, array[i]);
+        }
+        buffer.append(arrayEnd);
+    }
+
+    /**
+     * Append to the toString a summary of an
+     * int array.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name, typically not used as already appended
+     * @param array  the array to add to the toString,
+     *  not null
+     */
+    protected void appendSummary(StringBuffer buffer, String fieldName, int[] array) {
+        appendSummarySize(buffer, fieldName, array.length);
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Append to the toString a short
+     * array.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name
+     * @param array  the array to add to the toString
+     * @param fullDetail  true for detail, false
+     *  for summary info, null for style decides
+     */
+    public void append(StringBuffer buffer, String fieldName, short[] array, Boolean fullDetail) {
+        appendFieldStart(buffer, fieldName);
+
+        if (array == null) {
+            appendNullText(buffer, fieldName);
+
+        } else if (isFullDetail(fullDetail)) {
+            appendDetail(buffer, fieldName, array);
+
+        } else {
+            appendSummary(buffer, fieldName, array);
+        }
+
+        appendFieldEnd(buffer, fieldName);
+    }
+
+    /**
+     * Append to the toString the detail of a
+     * short array.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name, typically not used as already appended
+     * @param array  the array to add to the toString,
+     *  not null
+     */
+    protected void appendDetail(StringBuffer buffer, String fieldName, short[] array) {
+        buffer.append(arrayStart);
+        for (int i = 0; i < array.length; i++) {
+            if (i > 0) {
+                buffer.append(arraySeparator);
+            }
+            appendDetail(buffer, fieldName, array[i]);
+        }
+        buffer.append(arrayEnd);
+    }
+
+    /**
+     * Append to the toString a summary of a
+     * short array.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name, typically not used as already appended
+     * @param array  the array to add to the toString,
+     *  not null
+     */
+    protected void appendSummary(StringBuffer buffer, String fieldName, short[] array) {
+        appendSummarySize(buffer, fieldName, array.length);
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Append to the toString a byte
+     * array.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name
+     * @param array  the array to add to the toString
+     * @param fullDetail  true for detail, false
+     *  for summary info, null for style decides
+     */
+    public void append(StringBuffer buffer, String fieldName, byte[] array, Boolean fullDetail) {
+        appendFieldStart(buffer, fieldName);
+
+        if (array == null) {
+            appendNullText(buffer, fieldName);
+
+        } else if (isFullDetail(fullDetail)) {
+            appendDetail(buffer, fieldName, array);
+
+        } else {
+            appendSummary(buffer, fieldName, array);
+        }
+
+        appendFieldEnd(buffer, fieldName);
+    }
+
+    /**
+     * Append to the toString the detail of a
+     * byte array.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name, typically not used as already appended
+     * @param array  the array to add to the toString,
+     *  not null
+     */
+    protected void appendDetail(StringBuffer buffer, String fieldName, byte[] array) {
+        buffer.append(arrayStart);
+        for (int i = 0; i < array.length; i++) {
+            if (i > 0) {
+                buffer.append(arraySeparator);
+            }
+            appendDetail(buffer, fieldName, array[i]);
+        }
+        buffer.append(arrayEnd);
+    }
+
+    /**
+     * Append to the toString a summary of a
+     * byte array.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name, typically not used as already appended
+     * @param array  the array to add to the toString,
+     *  not null
+     */
+    protected void appendSummary(StringBuffer buffer, String fieldName, byte[] array) {
+        appendSummarySize(buffer, fieldName, array.length);
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Append to the toString a char
+     * array.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name
+     * @param array  the array to add to the toString
+     * @param fullDetail  true for detail, false
+     *  for summary info, null for style decides
+     */
+    public void append(StringBuffer buffer, String fieldName, char[] array, Boolean fullDetail) {
+        appendFieldStart(buffer, fieldName);
+
+        if (array == null) {
+            appendNullText(buffer, fieldName);
+
+        } else if (isFullDetail(fullDetail)) {
+            appendDetail(buffer, fieldName, array);
+
+        } else {
+            appendSummary(buffer, fieldName, array);
+        }
+
+        appendFieldEnd(buffer, fieldName);
+    }
+
+    /**
+     * Append to the toString the detail of a
+     * char array.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name, typically not used as already appended
+     * @param array  the array to add to the toString,
+     *  not null
+     */
+    protected void appendDetail(StringBuffer buffer, String fieldName, char[] array) {
+        buffer.append(arrayStart);
+        for (int i = 0; i < array.length; i++) {
+            if (i > 0) {
+                buffer.append(arraySeparator);
+            }
+            appendDetail(buffer, fieldName, array[i]);
+        }
+        buffer.append(arrayEnd);
+    }
+
+    /**
+     * Append to the toString a summary of a
+     * char array.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name, typically not used as already appended
+     * @param array  the array to add to the toString,
+     *  not null
+     */
+    protected void appendSummary(StringBuffer buffer, String fieldName, char[] array) {
+        appendSummarySize(buffer, fieldName, array.length);
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Append to the toString a double
+     * array.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name
+     * @param array  the array to add to the toString
+     * @param fullDetail  true for detail, false
+     *  for summary info, null for style decides
+     */
+    public void append(StringBuffer buffer, String fieldName, double[] array, Boolean fullDetail) {
+        appendFieldStart(buffer, fieldName);
+
+        if (array == null) {
+            appendNullText(buffer, fieldName);
+
+        } else if (isFullDetail(fullDetail)) {
+            appendDetail(buffer, fieldName, array);
+
+        } else {
+            appendSummary(buffer, fieldName, array);
+        }
+
+        appendFieldEnd(buffer, fieldName);
+    }
+
+    /**
+     * Append to the toString the detail of a
+     * double array.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name, typically not used as already appended
+     * @param array  the array to add to the toString,
+     *  not null
+     */
+    protected void appendDetail(StringBuffer buffer, String fieldName, double[] array) {
+        buffer.append(arrayStart);
+        for (int i = 0; i < array.length; i++) {
+            if (i > 0) {
+                buffer.append(arraySeparator);
+            }
+            appendDetail(buffer, fieldName, array[i]);
+        }
+        buffer.append(arrayEnd);
+    }
+
+    /**
+     * Append to the toString a summary of a
+     * double array.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name, typically not used as already appended
+     * @param array  the array to add to the toString,
+     *  not null
+     */
+    protected void appendSummary(StringBuffer buffer, String fieldName, double[] array) {
+        appendSummarySize(buffer, fieldName, array.length);
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Append to the toString a float
+     * array.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name
+     * @param array  the array to add to the toString
+     * @param fullDetail  true for detail, false
+     *  for summary info, null for style decides
+     */
+    public void append(StringBuffer buffer, String fieldName, float[] array, Boolean fullDetail) {
+        appendFieldStart(buffer, fieldName);
+
+        if (array == null) {
+            appendNullText(buffer, fieldName);
+
+        } else if (isFullDetail(fullDetail)) {
+            appendDetail(buffer, fieldName, array);
+
+        } else {
+            appendSummary(buffer, fieldName, array);
+        }
+
+        appendFieldEnd(buffer, fieldName);
+    }
+
+    /**
+     * Append to the toString the detail of a
+     * float array.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name, typically not used as already appended
+     * @param array  the array to add to the toString,
+     *  not null
+     */
+    protected void appendDetail(StringBuffer buffer, String fieldName, float[] array) {
+        buffer.append(arrayStart);
+        for (int i = 0; i < array.length; i++) {
+            if (i > 0) {
+                buffer.append(arraySeparator);
+            }
+            appendDetail(buffer, fieldName, array[i]);
+        }
+        buffer.append(arrayEnd);
+    }
+
+    /**
+     * Append to the toString a summary of a
+     * float array.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name, typically not used as already appended
+     * @param array  the array to add to the toString,
+     *  not null
+     */
+    protected void appendSummary(StringBuffer buffer, String fieldName, float[] array) {
+        appendSummarySize(buffer, fieldName, array.length);
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Append to the toString a boolean
+     * array.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name
+     * @param array  the array to add to the toString
+     * @param fullDetail  true for detail, false
+     *  for summary info, null for style decides
+     */
+    public void append(StringBuffer buffer, String fieldName, boolean[] array, Boolean fullDetail) {
+        appendFieldStart(buffer, fieldName);
+
+        if (array == null) {
+            appendNullText(buffer, fieldName);
+
+        } else if (isFullDetail(fullDetail)) {
+            appendDetail(buffer, fieldName, array);
+
+        } else {
+            appendSummary(buffer, fieldName, array);
+        }
+
+        appendFieldEnd(buffer, fieldName);
+    }
+
+    /**
+     * Append to the toString the detail of a
+     * boolean array.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name, typically not used as already appended
+     * @param array  the array to add to the toString,
+     *  not null
+     */
+    protected void appendDetail(StringBuffer buffer, String fieldName, boolean[] array) {
+        buffer.append(arrayStart);
+        for (int i = 0; i < array.length; i++) {
+            if (i > 0) {
+                buffer.append(arraySeparator);
+            }
+            appendDetail(buffer, fieldName, array[i]);
+        }
+        buffer.append(arrayEnd);
+    }
+
+    /**
+     * Append to the toString a summary of a
+     * boolean array.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name, typically not used as already appended
+     * @param array  the array to add to the toString,
+     *  not null
+     */
+    protected void appendSummary(StringBuffer buffer, String fieldName, boolean[] array) {
+        appendSummarySize(buffer, fieldName, array.length);
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Append to the toString the class name.
+     * 
+     * @param buffer  the StringBuffer to populate
+     * @param object  the Object whose name to output
+     */
+    protected void appendClassName(StringBuffer buffer, Object object) {
+        if (useClassName) {
+            if (useShortClassName) {
+                buffer.append(getShortClassName(object.getClass()));
+            } else {
+                buffer.append(object.getClass().getName());
+            }
+        }
+    }
+
+    /**
+     * Append the {@link System#identityHashCode(java.lang.Object)}.
+     * 
+     * @param buffer  the StringBuffer to populate
+     * @param object  the Object whose id to output
+     */
+    protected void appendIdentityHashCode(StringBuffer buffer, Object object) {
+        if (useIdentityHashCode) {
+            buffer.append('@');
+            buffer.append(Integer.toHexString(System.identityHashCode(object)));
+        }
+    }
+
+    /**
+     * Append to the toString the content start.
+     * 
+     * @param buffer  the StringBuffer to populate
+     */
+    protected void appendContentStart(StringBuffer buffer) {
+        buffer.append(contentStart);
+    }
+
+    /**
+     * Append to the toString the content end.
+     * 
+     * @param buffer  the StringBuffer to populate
+     */
+    protected void appendContentEnd(StringBuffer buffer) {
+        buffer.append(contentEnd);
+    }
+
+    /**
+     * Append to the toString an indicator for null.
+     *
+     * The default indicator is '<null>'.
+     * 
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name, typically not used as already appended
+     */
+    protected void appendNullText(StringBuffer buffer, String fieldName) {
+        buffer.append(nullText);
+    }
+
+    /**
+     * Append to the toString the field separator.
+     * 
+     * @param buffer  the StringBuffer to populate
+     */
+    protected void appendFieldSeparator(StringBuffer buffer) {
+        buffer.append(fieldSeparator);
+    }
+
+    /**
+     * Append to the toString the field start.
+     * 
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name
+     */
+    protected void appendFieldStart(StringBuffer buffer, String fieldName) {
+        if (useFieldNames && fieldName != null) {
+            buffer.append(fieldName);
+            buffer.append(fieldNameValueSeparator);
+        }
+    }
+
+    /**
+     * Append to the toString the field end.
+     * 
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name, typically not used as already appended
+     */
+    protected void appendFieldEnd(StringBuffer buffer, String fieldName) {
+        appendFieldSeparator(buffer);
+    }
+
+    /**
+     * Append to the toString a size summary.
+     *
+     * The size summary is used to summarize the contents of
+     * Collections, Maps and arrays.
+     *
+     * The output consists of a prefix, the passed in size
+     * and a suffix.
+     *
+     * The default format is '<size=n>'.
+     *
+     * @param buffer  the StringBuffer to populate
+     * @param fieldName  the field name, typically not used as already appended
+     * @param size  the size to append
+     */
+    protected void appendSummarySize(StringBuffer buffer, String fieldName, int size) {
+        buffer.append(sizeStartText);
+        buffer.append(size);
+        buffer.append(sizeEndText);
+    }
+
+    /**
+     * Is this field to be output in full detail.
+     *
+     * This method converts a detail request into a detail level.
+     * The calling code may request full detail (true),
+     * but a subclass might ignore that and always return
+     * false. The calling code may pass in
+     * null indicating that it doesn't care about
+     * the detail level. In this case the default detail level is
+     * used.
+     * 
+     * @param fullDetailRequest  the detail level requested
+     * @return whether full detail is to be shown
+     */
+    protected boolean isFullDetail(Boolean fullDetailRequest) {
+        if (fullDetailRequest == null) {
+            return defaultFullDetail;
+        }
+        return fullDetailRequest.booleanValue();
+    }
+
+    /**
+     * Gets the short class name for a class.
+     *
+     * The short class name is the classname excluding
+     * the package name.
+     *
+     * @param cls  the Class to get the short name of
+     * @return the short name
+     */
+    protected String getShortClassName(Class cls) {
+        return ClassUtils.getShortClassName(cls);
+    }
+
+    // Setters and getters for the customizable parts of the style
+    // These methods are not expected to be overridden, except to make public
+    // (They are not public so that immutable subclasses can be written)
+    //---------------------------------------------------------------------
+
+    /**
+     * Gets whether to use the class name.
+     *
+     * @return the current useClassName flag
+     */
+    protected boolean isUseClassName() {
+        return useClassName;
+    }
+
+    /**
+     * Sets whether to use the class name.
+     *
+     * @param useClassName  the new useClassName flag
+     */
+    protected void setUseClassName(boolean useClassName) {
+        this.useClassName = useClassName;
+    }
+
+    //---------------------------------------------------------------------
+
+    /**
+     * Gets whether to output short or long class names.
+     *
+     * @return the current useShortClassName flag
+     * @since 2.0
+     */
+    protected boolean isUseShortClassName() {
+        return useShortClassName;
+    }
+
+    /**
+     * Gets whether to output short or long class names.
+     *
+     * @return the current shortClassName flag
+     * @deprecated Use {@link #isUseShortClassName()}
+     *             Method will be removed in Commons Lang 3.0.
+     */
+    protected boolean isShortClassName() {
+        return useShortClassName;
+    }
+
+    /**
+     * Sets whether to output short or long class names.
+     *
+     * @param useShortClassName  the new useShortClassName flag
+     * @since 2.0
+     */
+    protected void setUseShortClassName(boolean useShortClassName) {
+        this.useShortClassName = useShortClassName;
+    }
+
+    /**
+     * Sets whether to output short or long class names.
+     *
+     * @param shortClassName  the new shortClassName flag
+     * @deprecated Use {@link #setUseShortClassName(boolean)}
+     *             Method will be removed in Commons Lang 3.0.
+     */
+    protected void setShortClassName(boolean shortClassName) {
+        this.useShortClassName = shortClassName;
+    }
+
+    //---------------------------------------------------------------------
+
+    /**
+     * Gets whether to use the identity hash code.
+     *
+     * @return the current useIdentityHashCode flag
+     */
+    protected boolean isUseIdentityHashCode() {
+        return useIdentityHashCode;
+    }
+
+    /**
+     * Sets whether to use the identity hash code.
+     *
+     * @param useIdentityHashCode  the new useIdentityHashCode flag
+     */
+    protected void setUseIdentityHashCode(boolean useIdentityHashCode) {
+        this.useIdentityHashCode = useIdentityHashCode;
+    }
+
+    //---------------------------------------------------------------------
+
+    /**
+     * Gets whether to use the field names passed in.
+     *
+     * @return the current useFieldNames flag
+     */
+    protected boolean isUseFieldNames() {
+        return useFieldNames;
+    }
+
+    /**
+     * Sets whether to use the field names passed in.
+     *
+     * @param useFieldNames  the new useFieldNames flag
+     */
+    protected void setUseFieldNames(boolean useFieldNames) {
+        this.useFieldNames = useFieldNames;
+    }
+
+    //---------------------------------------------------------------------
+
+    /**
+     * Gets whether to use full detail when the caller doesn't
+     * specify.
+     *
+     * @return the current defaultFullDetail flag
+     */
+    protected boolean isDefaultFullDetail() {
+        return defaultFullDetail;
+    }
+
+    /**
+     * Sets whether to use full detail when the caller doesn't
+     * specify.
+     *
+     * @param defaultFullDetail  the new defaultFullDetail flag
+     */
+    protected void setDefaultFullDetail(boolean defaultFullDetail) {
+        this.defaultFullDetail = defaultFullDetail;
+    }
+
+    //---------------------------------------------------------------------
+
+    /**
+     * Gets whether to output array content detail.
+     *
+     * @return the current array content detail setting
+     */
+    protected boolean isArrayContentDetail() {
+        return arrayContentDetail;
+    }
+
+    /**
+     * Sets whether to output array content detail.
+     *
+     * @param arrayContentDetail  the new arrayContentDetail flag
+     */
+    protected void setArrayContentDetail(boolean arrayContentDetail) {
+        this.arrayContentDetail = arrayContentDetail;
+    }
+
+    //---------------------------------------------------------------------
+
+    /**
+     * Gets the array start text.
+     *
+     * @return the current array start text
+     */
+    protected String getArrayStart() {
+        return arrayStart;
+    }
+
+    /**
+     * Sets the array start text.
+     *
+     * null is accepted, but will be converted to
+     * an empty String.
+     *
+     * @param arrayStart  the new array start text
+     */
+    protected void setArrayStart(String arrayStart) {
+        if (arrayStart == null) {
+            arrayStart = "";
+        }
+        this.arrayStart = arrayStart;
+    }
+
+    //---------------------------------------------------------------------
+
+    /**
+     * Gets the array end text.
+     *
+     * @return the current array end text
+     */
+    protected String getArrayEnd() {
+        return arrayEnd;
+    }
+
+    /**
+     * Sets the array end text.
+     *
+     * null is accepted, but will be converted to
+     * an empty String.
+     *
+     * @param arrayEnd  the new array end text
+     */
+    protected void setArrayEnd(String arrayEnd) {
+        if (arrayStart == null) {
+            arrayStart = "";
+        }
+        this.arrayEnd = arrayEnd;
+    }
+
+    //---------------------------------------------------------------------
+
+    /**
+     * Gets the array separator text.
+     *
+     * @return the current array separator text
+     */
+    protected String getArraySeparator() {
+        return arraySeparator;
+    }
+
+    /**
+     * Sets the array separator text.
+     *
+     * null is accepted, but will be converted to
+     * an empty String.
+     *
+     * @param arraySeparator  the new array separator text
+     */
+    protected void setArraySeparator(String arraySeparator) {
+        if (arraySeparator == null) {
+            arraySeparator = "";
+        }
+        this.arraySeparator = arraySeparator;
+    }
+
+    //---------------------------------------------------------------------
+
+    /**
+     * Gets the content start text.
+     *
+     * @return the current content start text
+     */
+    protected String getContentStart() {
+        return contentStart;
+    }
+
+    /**
+     * Sets the content start text.
+     *
+     * null is accepted, but will be converted to
+     * an empty String.
+     *
+     * @param contentStart  the new content start text
+     */
+    protected void setContentStart(String contentStart) {
+        if (contentStart == null) {
+            contentStart = "";
+        }
+        this.contentStart = contentStart;
+    }
+
+    //---------------------------------------------------------------------
+
+    /**
+     * Gets the content end text.
+     *
+     * @return the current content end text
+     */
+    protected String getContentEnd() {
+        return contentEnd;
+    }
+
+    /**
+     * Sets the content end text.
+     *
+     * null is accepted, but will be converted to
+     * an empty String.
+     *
+     * @param contentEnd  the new content end text
+     */
+    protected void setContentEnd(String contentEnd) {
+        if (contentEnd == null) {
+            contentEnd = "";
+        }
+        this.contentEnd = contentEnd;
+    }
+
+    //---------------------------------------------------------------------
+
+    /**
+     * Gets the field name value separator text.
+     *
+     * @return the current field name value separator text
+     */
+    protected String getFieldNameValueSeparator() {
+        return fieldNameValueSeparator;
+    }
+
+    /**
+     * Sets the field name value separator text.
+     *
+     * null is accepted, but will be converted to
+     * an empty String.
+     *
+     * @param fieldNameValueSeparator  the new field name value separator text
+     */
+    protected void setFieldNameValueSeparator(String fieldNameValueSeparator) {
+        if (fieldNameValueSeparator == null) {
+            fieldNameValueSeparator = "";
+        }
+        this.fieldNameValueSeparator = fieldNameValueSeparator;
+    }
+
+    //---------------------------------------------------------------------
+
+    /**
+     * Gets the field separator text.
+     *
+     * @return the current field separator text
+     */
+    protected String getFieldSeparator() {
+        return fieldSeparator;
+    }
+
+    /**
+     * Sets the field separator text.
+     *
+     * null is accepted, but will be converted to
+     * an empty String.
+     *
+     * @param fieldSeparator  the new field separator text
+     */
+    protected void setFieldSeparator(String fieldSeparator) {
+        if (fieldSeparator == null) {
+            fieldSeparator = "";
+        }
+        this.fieldSeparator = fieldSeparator;
+    }
+
+    //---------------------------------------------------------------------
+
+    /**
+     * Gets whether the field separator should be added at the start 
+     * of each buffer.
+     * 
+     * @return the fieldSeparatorAtStart flag
+     * @since 2.0
+     */
+    protected boolean isFieldSeparatorAtStart() {
+        return fieldSeparatorAtStart;
+    }
+
+    /**
+     * Sets whether the field separator should be added at the start 
+     * of each buffer.
+     * 
+     * @param fieldSeparatorAtStart  the fieldSeparatorAtStart flag
+     * @since 2.0
+     */
+    protected void setFieldSeparatorAtStart(boolean fieldSeparatorAtStart) {
+        this.fieldSeparatorAtStart = fieldSeparatorAtStart;
+    }
+
+    //---------------------------------------------------------------------
+
+    /**
+     * Gets whether the field separator should be added at the end 
+     * of each buffer.
+     * 
+     * @return fieldSeparatorAtEnd flag
+     * @since 2.0
+     */
+    protected boolean isFieldSeparatorAtEnd() {
+        return fieldSeparatorAtEnd;
+    }
+
+    /**
+     * Sets whether the field separator should be added at the end 
+     * of each buffer.
+     * 
+     * @param fieldSeparatorAtEnd  the fieldSeparatorAtEnd flag
+     * @since 2.0
+     */
+    protected void setFieldSeparatorAtEnd(boolean fieldSeparatorAtEnd) {
+        this.fieldSeparatorAtEnd = fieldSeparatorAtEnd;
+    }
+
+    //---------------------------------------------------------------------
+
+    /**
+     * Gets the text to output when null found.
+     *
+     * @return the current text to output when null found
+     */
+    protected String getNullText() {
+        return nullText;
+    }
+
+    /**
+     * Sets the text to output when null found.
+     *
+     * null is accepted, but will be converted to
+     * an empty String.
+     *
+     * @param nullText  the new text to output when null found
+     */
+    protected void setNullText(String nullText) {
+        if (nullText == null) {
+            nullText = "";
+        }
+        this.nullText = nullText;
+    }
+
+    //---------------------------------------------------------------------
+
+    /**
+     * Gets the start text to output when a Collection,
+     * Map or array size is output.
+     *
+     * This is output before the size value.
+     *
+     * @return the current start of size text
+     */
+    protected String getSizeStartText() {
+        return sizeStartText;
+    }
+
+    /**
+     * Sets the start text to output when a Collection,
+     * Map or array size is output.
+     *
+     * This is output before the size value.
+     *
+     * null is accepted, but will be converted to
+     * an empty String.
+     *
+     * @param sizeStartText  the new start of size text
+     */
+    protected void setSizeStartText(String sizeStartText) {
+        if (sizeStartText == null) {
+            sizeStartText = "";
+        }
+        this.sizeStartText = sizeStartText;
+    }
+
+    //---------------------------------------------------------------------
+
+    /**
+     * Gets the end text to output when a Collection,
+     * Map or array size is output.
+     *
+     * This is output after the size value.
+     *
+     * @return the current end of size text
+     */
+    protected String getSizeEndText() {
+        return sizeEndText;
+    }
+
+    /**
+     * Sets the end text to output when a Collection,
+     * Map or array size is output.
+     *
+     * This is output after the size value.
+     *
+     * null is accepted, but will be converted to
+     * an empty String.
+     *
+     * @param sizeEndText  the new end of size text
+     */
+    protected void setSizeEndText(String sizeEndText) {
+        if (sizeEndText == null) {
+            sizeEndText = "";
+        }
+        this.sizeEndText = sizeEndText;
+    }
+
+    //---------------------------------------------------------------------
+
+    /**
+     * Gets the start text to output when an Object is
+     * output in summary mode.
+     *
+     * This is output before the size value.
+     *
+     * @return the current start of summary text
+     */
+    protected String getSummaryObjectStartText() {
+        return summaryObjectStartText;
+    }
+
+    /**
+     * Sets the start text to output when an Object is
+     * output in summary mode.
+     *
+     * This is output before the size value.
+     *
+     * null is accepted, but will be converted to
+     * an empty String.
+     *
+     * @param summaryObjectStartText  the new start of summary text
+     */
+    protected void setSummaryObjectStartText(String summaryObjectStartText) {
+        if (summaryObjectStartText == null) {
+            summaryObjectStartText = "";
+        }
+        this.summaryObjectStartText = summaryObjectStartText;
+    }
+
+    //---------------------------------------------------------------------
+
+    /**
+     * Gets the end text to output when an Object is
+     * output in summary mode.
+     *
+     * This is output after the size value.
+     *
+     * @return the current end of summary text
+     */
+    protected String getSummaryObjectEndText() {
+        return summaryObjectEndText;
+    }
+
+    /**
+     * Sets the end text to output when an Object is
+     * output in summary mode.
+     *
+     * This is output after the size value.
+     *
+     * null is accepted, but will be converted to
+     * an empty String.
+     *
+     * @param summaryObjectEndText  the new end of summary text
+     */
+    protected void setSummaryObjectEndText(String summaryObjectEndText) {
+        if (summaryObjectEndText == null) {
+            summaryObjectEndText = "";
+        }
+        this.summaryObjectEndText = summaryObjectEndText;
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * Default ToStringStyle.
+     *
+     * This is an inner class rather than using
+     * StandardToStringStyle to ensure its immutability.
+     */
+    private static final class DefaultToStringStyle extends ToStringStyle {
+
+        /**
+         * Constructor.
+         *
+         * Use the static constant rather than instantiating.
+         */
+        private DefaultToStringStyle() {
+            super();
+        }
+
+        /**
+         * Ensure Singleton after serialization.
+         *
+         * @return the singleton
+         */
+        private Object readResolve() {
+            return ToStringStyle.DEFAULT_STYLE;
+        }
+
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * ToStringStyle that does not print out
+     * the field names.
+     *
+     * This is an inner class rather than using
+     * StandardToStringStyle to ensure its immutability.
+     */
+    private static final class NoFieldNameToStringStyle extends ToStringStyle {
+
+        /**
+         * 
Constructor.
+         *
+         * Use the static constant rather than instantiating.
+         */
+        private NoFieldNameToStringStyle() {
+            super();
+            this.setUseFieldNames(false);
+        }
+
+        /**
+         * Ensure Singleton after serialization.
+         *
+         * @return the singleton
+         */
+        private Object readResolve() {
+            return ToStringStyle.NO_FIELD_NAMES_STYLE;
+        }
+
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * ToStringStyle that does not print out the
+     * classname, identity hashcode, content start or field name.
+     *
+     * This is an inner class rather than using
+     * StandardToStringStyle to ensure its immutability.
+     */
+    private static final class SimpleToStringStyle extends ToStringStyle {
+
+        /**
+         * Constructor.
+         *
+         * Use the static constant rather than instantiating.
+         */
+        private SimpleToStringStyle() {
+            super();
+            this.setUseClassName(false);
+            this.setUseIdentityHashCode(false);
+            this.setUseFieldNames(false);
+            this.setContentStart("");
+            this.setContentEnd("");
+        }
+
+        /**
+         * Ensure Singleton after serialization.
+         * @return the singleton
+         */
+        private Object readResolve() {
+            return ToStringStyle.SIMPLE_STYLE;
+        }
+
+    }
+
+    //----------------------------------------------------------------------------
+
+    /**
+     * ToStringStyle that outputs on multiple lines.
+     *
+     * This is an inner class rather than using
+     * StandardToStringStyle to ensure its immutability.
+     */
+    private static final class MultiLineToStringStyle extends ToStringStyle {
+
+        /**
+         * Constructor.
+         *
+         * Use the static constant rather than instantiating.
+         */
+        private MultiLineToStringStyle() {
+            super();
+            this.setContentStart("[");
+            this.setFieldSeparator(SystemUtils.LINE_SEPARATOR + "  ");
+            this.setFieldSeparatorAtStart(true);
+            this.setContentEnd(SystemUtils.LINE_SEPARATOR + "]");
+        }
+
+        /**
+         * Ensure Singleton after serialization.
+         *
+         * @return the singleton
+         */
+        private Object readResolve() {
+            return ToStringStyle.MULTI_LINE_STYLE;
+        }
+
+    }
+
+    //----------------------------------------------------------------------------
+
+// Removed, as the XML style needs more work for escaping characters, arrays,
+// collections, maps and embedded beans.
+//    /**
+//     * ToStringStyle that outputs in XML style
+//     */
+//    private static class XMLToStringStyle extends ToStringStyle {
+//        
+//        /**
+//         * Constructor - use the static constant rather than instantiating.
+//         */
+//        private XMLToStringStyle() {
+//            super();
+//            nullText = "null";
+//            sizeStartText = "size=";
+//            sizeEndText = "";
+//        }
+//        
+//        /**
+//         * @see ToStringStyle#appendStart(StringBuffer, Object)
+//         */
+//        public void appendStart(StringBuffer buffer, Object object) {
+//            buffer.append('<');
+//            buffer.append(getShortClassName(object.getClass()));
+//            buffer.append(" class=\"");
+//            appendClassName(buffer, object);
+//            buffer.append("\" hashCode=\"");
+//            appendIdentityHashCode(buffer, object);
+//            buffer.append("\">");
+//            buffer.append(SystemUtils.LINE_SEPARATOR);
+//            buffer.append("  ");
+//        }
+//
+//        /**
+//         * @see ToStringStyle#appendFieldStart(StringBuffer, String)
+//         */
+//        protected void appendFieldStart(StringBuffer buffer, String fieldName) {
+//            buffer.append('<');
+//            buffer.append(fieldName);
+//            buffer.append('>');
+//        }
+//
+//        /**
+//         * @see ToStringStyle#appendFieldEnd(StringBuffer, String)
+//         */
+//        protected void appendFieldEnd(StringBuffer buffer, String fieldName) {
+//            buffer.append("");
+//            buffer.append(fieldName);
+//            buffer.append('>');
+//            buffer.append(SystemUtils.LINE_SEPARATOR);
+//            buffer.append("  ");
+//        }
+//
+//        /**
+//         * @see ToStringStyle#appendEnd(StringBuffer, Object)
+//         */
+//        public void appendEnd(StringBuffer buffer, Object object) {
+//            int len = buffer.length();
+//            if (len > 2 && buffer.charAt(len - 1) == ' ' && buffer.charAt(len - 2) == ' ') {
+//                buffer.setLength(len - 2);
+//            }
+//            buffer.append("");
+//            buffer.append(getShortClassName(object.getClass()));
+//            buffer.append("\">");
+//        }
+//
+//    }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/package.html
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/builder/package.html,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/builder/package.html	30 Aug 2012 16:24:43 -0000	1.1
@@ -0,0 +1,7 @@
+
+
+Assists in creating consistent equals(Object), toString(),
+hashCode(), and compareTo(Object) methods.
+@since 1.0
+
+
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/enum/Enum.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/enum/Enum.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/enum/Enum.java	30 Aug 2012 16:24:43 -0000	1.1
@@ -0,0 +1,595 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang.enum;
+
+import java.io.Serializable;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+import org.apache.commons.lang.ClassUtils;
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * Abstract superclass for type-safe enums.
+ *
+ * One feature of the C programming language lacking in Java is enumerations. The
+ * C implementation based on ints was poor and open to abuse. The original Java
+ * recommendation and most of the JDK also uses int constants. It has been recognised
+ * however that a more robust type-safe class-based solution can be designed. This
+ * class follows the basic Java type-safe enumeration pattern.
+ *
+ * NOTE:Due to the way in which Java ClassLoaders work, comparing
+ * Enum objects should always be done using equals(), not ==.
+ * The equals() method will try == first so in most cases the effect is the same.
+ * 
+ * Of course, if you actually want (or don't mind) Enums in different class
+ * loaders being non-equal, then you can use ==.
+ * 
+ * Simple Enums
+ *
+ * To use this class, it must be subclassed. For example:
+ *
+ * 
+ * public final class ColorEnum extends Enum {
+ *   public static final ColorEnum RED = new ColorEnum("Red");
+ *   public static final ColorEnum GREEN = new ColorEnum("Green");
+ *   public static final ColorEnum BLUE = new ColorEnum("Blue");
+ *
+ *   private ColorEnum(String color) {
+ *     super(color);
+ *   }
+ * 
+ *   public static ColorEnum getEnum(String color) {
+ *     return (ColorEnum) getEnum(ColorEnum.class, color);
+ *   }
+ * 
+ *   public static Map getEnumMap() {
+ *     return getEnumMap(ColorEnum.class);
+ *   }
+ * 
+ *   public static List getEnumList() {
+ *     return getEnumList(ColorEnum.class);
+ *   }
+ * 
+ *   public static Iterator iterator() {
+ *     return iterator(ColorEnum.class);
+ *   }
+ * }
+ * 
+ *
+ * As shown, each enum has a name. This can be accessed using getName.
+ *
+ * The getEnum and iterator methods are recommended.
+ * Unfortunately, Java restrictions require these to be coded as shown in each subclass.
+ * An alternative choice is to use the {@link EnumUtils} class.
+ * 
+ * Subclassed Enums
+ * A hierarchy of Enum classes can be built. In this case, the superclass is
+ * unaffected by the addition of subclasses (as per normal Java). The subclasses
+ * may add additional Enum constants of the type of the superclass. The
+ * query methods on the subclass will return all of the Enum constants from the
+ * superclass and subclass.
+ *
+ * 
+ * public final class ExtraColorEnum extends ColorEnum {
+ *   // NOTE: Color enum declared above is final, change that to get this
+ *   // example to compile.
+ *   public static final ColorEnum YELLOW = new ExtraColorEnum("Yellow");
+ *
+ *   private ExtraColorEnum(String color) {
+ *     super(color);
+ *   }
+ * 
+ *   public static ColorEnum getEnum(String color) {
+ *     return (ColorEnum) getEnum(ExtraColorEnum.class, color);
+ *   }
+ * 
+ *   public static Map getEnumMap() {
+ *     return getEnumMap(ExtraColorEnum.class);
+ *   }
+ * 
+ *   public static List getEnumList() {
+ *     return getEnumList(ExtraColorEnum.class);
+ *   }
+ * 
+ *   public static Iterator iterator() {
+ *     return iterator(ExtraColorEnum.class);
+ *   }
+ * }
+ * 
+ *
+ * This example will return RED, GREEN, BLUE, YELLOW from the List and iterator
+ * methods in that order. The RED, GREEN and BLUE instances will be the same (==) 
+ * as those from the superclass ColorEnum. Note that YELLOW is declared as a
+ * ColorEnum and not an ExtraColorEnum.
+ * 
+ * Functional Enums
+ *
+ * The enums can have functionality by defining subclasses and
+ * overriding the getEnumClass() method:
+ * 
+ * 
+ *   public static final OperationEnum PLUS = new PlusOperation();
+ *   private static final class PlusOperation extends OperationEnum {
+ *     private PlusOperation() {
+ *       super("Plus");
+ *     }
+ *     public int eval(int a, int b) {
+ *       return (a + b);
+ *     }
+ *   }
+ *   public static final OperationEnum MINUS = new MinusOperation();
+ *   private static final class MinusOperation extends OperationEnum {
+ *     private MinusOperation() {
+ *       super("Minus");
+ *     }
+ *     public int eval(int a, int b) {
+ *       return (a - b);
+ *     }
+ *   }
+ *
+ *   private OperationEnum(String color) {
+ *     super(color);
+ *   }
+ * 
+ *   public final Class getEnumClass() {     // NOTE: new method!
+ *     return OperationEnum.class;
+ *   }
+ *
+ *   public abstract double eval(double a, double b);
+ * 
+ *   public static OperationEnum getEnum(String name) {
+ *     return (OperationEnum) getEnum(OperationEnum.class, name);
+ *   }
+ * 
+ *   public static Map getEnumMap() {
+ *     return getEnumMap(OperationEnum.class);
+ *   }
+ * 
+ *   public static List getEnumList() {
+ *     return getEnumList(OperationEnum.class);
+ *   }
+ * 
+ *   public static Iterator iterator() {
+ *     return iterator(OperationEnum.class);
+ *   }
+ * }
+ * 
+ * The code above will work on JDK 1.2. If JDK1.3 and later is used,
+ * the subclasses may be defined as anonymous.
+ *
+ * @author Apache Avalon project
+ * @author Stephen Colebourne
+ * @author Chris Webb
+ * @author Mike Bowler
+ * @since 1.0
+ * @version $Id: Enum.java,v 1.1 2012/08/30 16:24:43 marcin Exp $
+ */
+public abstract class Enum implements Comparable, Serializable {
+
+    /** Lang version 1.0.1 serial compatability */
+    private static final long serialVersionUID = -487045951170455942L;
+    
+    // After discussion, the default size for HashMaps is used, as the
+    // sizing algorithm changes across the JDK versions
+    /**
+     * An empty Map, as JDK1.2 didn't have an empty map.
+     */
+    private static final Map EMPTY_MAP = Collections.unmodifiableMap(new HashMap(0));
+    
+    /**
+     * Map, key of class name, value of Entry.
+     */
+    private static final Map cEnumClasses = new HashMap();
+    
+    /**
+     * The string representation of the Enum.
+     */
+    private final String iName;
+    
+    /**
+     * The hashcode representation of the Enum.
+     */
+    private transient final int iHashCode;
+    
+    /**
+     * The toString representation of the Enum.
+     * @since 2.0
+     */
+    protected transient String iToString = null;
+
+    /**
+     * Enable the iterator to retain the source code order.
+     */
+    private static class Entry {
+        /**
+         * Map of Enum name to Enum.
+         */
+        final Map map = new HashMap();
+        /**
+         * Map of Enum name to Enum.
+         */
+        final Map unmodifiableMap = Collections.unmodifiableMap(map);
+        /**
+         * List of Enums in source code order.
+         */
+        final List list = new ArrayList(25);
+        /**
+         * Map of Enum name to Enum.
+         */
+        final List unmodifiableList = Collections.unmodifiableList(list);
+
+        /**
+         * Restrictive constructor.
+         */
+        private Entry() {
+        }
+    }
+
+    /**
+     * Constructor to add a new named item to the enumeration.
+     *
+     * @param name  the name of the enum object,
+     *  must not be empty or null
+     * @throws IllegalArgumentException if the name is null
+     *  or an empty string
+     * @throws IllegalArgumentException if the getEnumClass() method returns
+     *  a null or invalid Class
+     */
+    protected Enum(String name) {
+        super();
+        init(name);
+        iName = name;
+        iHashCode = 7 + getEnumClass().hashCode() + 3 * name.hashCode();
+        // cannot create toString here as subclasses may want to include other data
+    }
+
+    /**
+     * Initializes the enumeration.
+     * 
+     * @param name  the enum name
+     * @throws IllegalArgumentException if the name is null or empty or duplicate
+     * @throws IllegalArgumentException if the enumClass is null or invalid
+     */
+    private void init(String name) {
+        if (StringUtils.isEmpty(name)) {
+            throw new IllegalArgumentException("The Enum name must not be empty or null");
+        }
+        
+        Class enumClass = getEnumClass();
+        if (enumClass == null) {
+            throw new IllegalArgumentException("getEnumClass() must not be null");
+        }
+        Class cls = getClass();
+        boolean ok = false;
+        while (cls != null && cls != Enum.class && cls != ValuedEnum.class) {
+            if (cls == enumClass) {
+                ok = true;
+                break;
+            }
+            cls = cls.getSuperclass();
+        }
+        if (ok == false) {
+            throw new IllegalArgumentException("getEnumClass() must return a superclass of this class");
+        }
+        
+        // create entry
+        Entry entry = (Entry) cEnumClasses.get(enumClass);
+        if (entry == null) {
+            entry = createEntry(enumClass);
+            cEnumClasses.put(enumClass, entry);
+        }
+        if (entry.map.containsKey(name)) {
+            throw new IllegalArgumentException("The Enum name must be unique, '" + name + "' has already been added");
+        }
+        entry.map.put(name, this);
+        entry.list.add(this);
+    }
+
+    /**
+     * Handle the deserialization of the class to ensure that multiple
+     * copies are not wastefully created, or illegal enum types created.
+     *
+     * @return the resolved object
+     */
+    protected Object readResolve() {
+        Entry entry = (Entry) cEnumClasses.get(getEnumClass());
+        if (entry == null) {
+            return null;
+        }
+        return (Enum) entry.map.get(getName());
+    }
+    
+    //--------------------------------------------------------------------------------
+
+    /**
+     * Gets an Enum object by class and name.
+     * 
+     * @param enumClass  the class of the Enum to get, must not
+     *  be null
+     * @param name  the name of the Enum to get,
+     *  may be null
+     * @return the enum object, or null if the enum does not exist
+     * @throws IllegalArgumentException if the enum class
+     *  is null
+     */
+    protected static Enum getEnum(Class enumClass, String name) {
+        Entry entry = getEntry(enumClass);
+        if (entry == null) {
+            return null;
+        }
+        return (Enum) entry.map.get(name);
+    }
+
+    /**
+     * Gets the Map of Enum objects by
+     * name using the Enum class.
+     *
+     * If the requested class has no enum objects an empty
+     * Map is returned.
+     * 
+     * @param enumClass  the class of the Enum to get,
+     *  must not be null
+     * @return the enum object Map
+     * @throws IllegalArgumentException if the enum class is null
+     * @throws IllegalArgumentException if the enum class is not a subclass of Enum
+     */
+    protected static Map getEnumMap(Class enumClass) {
+        Entry entry = getEntry(enumClass);
+        if (entry == null) {
+            return EMPTY_MAP;
+        }
+        return entry.unmodifiableMap;
+    }
+
+    /**
+     * Gets the List of Enum objects using the
+     * Enum class.
+     *
+     * The list is in the order that the objects were created (source code order).
+     * If the requested class has no enum objects an empty List is
+     * returned.
+     * 
+     * @param enumClass  the class of the Enum to get,
+     *  must not be null
+     * @return the enum object Map
+     * @throws IllegalArgumentException if the enum class is null
+     * @throws IllegalArgumentException if the enum class is not a subclass of Enum
+     */
+    protected static List getEnumList(Class enumClass) {
+        Entry entry = getEntry(enumClass);
+        if (entry == null) {
+            return Collections.EMPTY_LIST;
+        }
+        return entry.unmodifiableList;
+    }
+
+    /**
+     * Gets an Iterator over the Enum objects in
+     * an Enum class.
+     *
+     * The Iterator is in the order that the objects were
+     * created (source code order). If the requested class has no enum
+     * objects an empty Iterator is returned.
+     * 
+     * @param enumClass  the class of the Enum to get,
+     *  must not be null
+     * @return an iterator of the Enum objects
+     * @throws IllegalArgumentException if the enum class is null
+     * @throws IllegalArgumentException if the enum class is not a subclass of Enum
+     */
+    protected static Iterator iterator(Class enumClass) {
+        return Enum.getEnumList(enumClass).iterator();
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Gets an Entry from the map of Enums.
+     * 
+     * @param enumClass  the class of the Enum to get
+     * @return the enum entry
+     */
+    private static Entry getEntry(Class enumClass) {
+        if (enumClass == null) {
+            throw new IllegalArgumentException("The Enum Class must not be null");
+        }
+        if (Enum.class.isAssignableFrom(enumClass) == false) {
+            throw new IllegalArgumentException("The Class must be a subclass of Enum");
+        }
+        Entry entry = (Entry) cEnumClasses.get(enumClass);
+        return entry;
+    }
+    
+    /**
+     * Creates an Entry for storing the Enums.
+     *
+     * This accounts for subclassed Enums.
+     * 
+     * @param enumClass  the class of the Enum to get
+     * @return the enum entry
+     */
+    private static Entry createEntry(Class enumClass) {
+        Entry entry = new Entry();
+        Class cls = enumClass.getSuperclass();
+        while (cls != null && cls != Enum.class && cls != ValuedEnum.class) {
+            Entry loopEntry = (Entry) cEnumClasses.get(cls);
+            if (loopEntry != null) {
+                entry.list.addAll(loopEntry.list);
+                entry.map.putAll(loopEntry.map);
+                break;  // stop here, as this will already have had superclasses added
+            }
+            cls = cls.getSuperclass();
+        }
+        return entry;
+    }
+    
+    //-----------------------------------------------------------------------
+    /**
+     * Retrieve the name of this Enum item, set in the constructor.
+     * 
+     * @return the String name of this Enum item
+     */
+    public final String getName() {
+        return iName;
+    }
+
+    /**
+     * Retrieves the Class of this Enum item, set in the constructor.
+     * 
+     * This is normally the same as getClass(), but for
+     * advanced Enums may be different. If overridden, it must return a
+     * constant value.
+     * 
+     * @return the Class of the enum
+     * @since 2.0
+     */
+    public Class getEnumClass() {
+        return getClass();
+    }
+
+    /**
+     * Tests for equality.
+     *
+     * Two Enum objects are considered equal
+     * if they have the same class names and the same names.
+     * Identity is tested for first, so this method usually runs fast.
+     *
+     * @param other  the other object to compare for equality
+     * @return true if the Enums are equal
+     */
+    public final boolean equals(Object other) {
+        if (other == this) {
+            return true;
+        } else if (other == null) {
+            return false;
+        } else if (other.getClass() == this.getClass()) {
+            // shouldn't happen, but...
+            return iName.equals(((Enum) other).iName);
+        } else if (((Enum) other).getEnumClass().getName().equals(getEnumClass().getName())) {
+            // different classloaders
+            try {
+                // try to avoid reflection
+                return iName.equals(((Enum) other).iName);
+
+            } catch (ClassCastException ex) {
+                // use reflection
+                try {
+                    Method mth = other.getClass().getMethod("getName", null);
+                    String name = (String) mth.invoke(other, null);
+                    return iName.equals(name);
+                } catch (NoSuchMethodException ex2) {
+                    // ignore - should never happen
+                } catch (IllegalAccessException ex2) {
+                    // ignore - should never happen
+                } catch (InvocationTargetException ex2) {
+                    // ignore - should never happen
+                }
+                return false;
+            }
+        } else {
+            return false;
+        }
+    }
+
+    /**
+     * Returns a suitable hashCode for the enumeration.
+     *
+     * @return a hashcode based on the name
+     */
+    public final int hashCode() {
+        return iHashCode;
+    }
+
+    /**
+     * Tests for order.
+     *
+     * The default ordering is alphabetic by name, but this
+     * can be overridden by subclasses.
+     * 
+     * @see java.lang.Comparable#compareTo(Object)
+     * @param other  the other object to compare to
+     * @return -ve if this is less than the other object, +ve if greater
+     *  than, 0 of equal
+     * @throws ClassCastException if other is not an Enum
+     * @throws NullPointerException if other is null
+     */
+    public int compareTo(Object other) {
+        if (other == this) {
+            return 0;
+        }
+        return iName.compareTo(((Enum) other).iName);
+    }
+
+    /**
+     * Human readable description of this Enum item.
+     * 
+     * @return String in the form type[name], for example:
+     * Color[Red]. Note that the package name is stripped from
+     * the type name.
+     */
+    public String toString() {
+        if (iToString == null) {
+            String shortName = ClassUtils.getShortClassName(getEnumClass());
+            iToString = shortName + "[" + getName() + "]";
+        }
+        return iToString;
+    }
+    
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/enum/EnumUtils.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/enum/EnumUtils.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/enum/EnumUtils.java	30 Aug 2012 16:24:44 -0000	1.1
@@ -0,0 +1,160 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang.enum;
+
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * Utility class for accessing and manipulating {@link Enum}s.
+ *
+ * @see Enum
+ * @see ValuedEnum
+ * @author Stephen Colebourne
+ * @author Gary Gregory
+ * @since 1.0
+ * @version $Id: EnumUtils.java,v 1.1 2012/08/30 16:24:44 marcin Exp $
+ */
+public class EnumUtils {
+
+    /**
+     * Public constructor. This class should not normally be instantiated.
+     * @since 2.0
+     */
+    public EnumUtils() {
+    }
+
+    /**
+     * Gets an Enum object by class and name.
+     * 
+     * @param enumClass  the class of the Enum to get
+     * @param name  the name of the Enum to get, may be null
+     * @return the enum object
+     * @throws IllegalArgumentException if the enum class is null
+     */
+    public static Enum getEnum(Class enumClass, String name) {
+        return Enum.getEnum(enumClass, name);
+    }
+
+    /**
+     * Gets a ValuedEnum object by class and value.
+     * 
+     * @param enumClass  the class of the Enum to get
+     * @param value  the value of the Enum to get
+     * @return the enum object, or null if the enum does not exist
+     * @throws IllegalArgumentException if the enum class is null
+     */
+    public static ValuedEnum getEnum(Class enumClass, int value) {
+        return (ValuedEnum) ValuedEnum.getEnum(enumClass, value);
+    }
+
+    /**
+     * Gets the Map of Enum objects by
+     * name using the Enum class.
+     *
+     * If the requested class has no enum objects an empty
+     * Map is returned. The Map is unmodifiable.
+     * 
+     * @param enumClass  the class of the Enum to get
+     * @return the enum object Map
+     * @throws IllegalArgumentException if the enum class is null
+     * @throws IllegalArgumentException if the enum class is not a subclass
+     *  of Enum
+     */
+    public static Map getEnumMap(Class enumClass) {
+        return Enum.getEnumMap(enumClass);
+    }
+
+    /**
+     * Gets the List of Enum objects using
+     * the Enum class.
+     *
+     * The list is in the order that the objects were created
+     * (source code order).
+     *
+     * If the requested class has no enum objects an empty
+     * List is returned. The List is unmodifiable.
+     * 
+     * @param enumClass  the class of the Enum to get
+     * @return the enum object Map
+     * @throws IllegalArgumentException if the enum class is null
+     * @throws IllegalArgumentException if the enum class is not a subclass
+     *  of Enum
+     */
+    public static List getEnumList(Class enumClass) {
+        return Enum.getEnumList(enumClass);
+    }
+
+    /**
+     * Gets an Iterator over the Enum objects
+     * in an Enum class.
+     *
+     * The iterator is in the order that the objects were created
+     * (source code order).
+     *
+     * If the requested class has no enum objects an empty
+     * Iterator is returned. The Iterator
+     * is unmodifiable.
+     * 
+     * @param enumClass  the class of the Enum to get
+     * @return an Iterator of the Enum objects
+     * @throws IllegalArgumentException if the enum class is null
+     * @throws IllegalArgumentException if the enum class is not a subclass of Enum
+     */
+    public static Iterator iterator(Class enumClass) {
+        return Enum.getEnumList(enumClass).iterator();
+    }
+    
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/enum/ValuedEnum.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/enum/ValuedEnum.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/enum/ValuedEnum.java	30 Aug 2012 16:24:43 -0000	1.1
@@ -0,0 +1,225 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang.enum;
+
+import java.util.Iterator;
+import java.util.List;
+
+import org.apache.commons.lang.ClassUtils;
+
+/**
+ * Abstract superclass for type-safe enums with integer values suitable
+ * for use in switch statements.
+ *
+ * NOTE:Due to the way in which Java ClassLoaders work, comparing
+ * Enum objects should always be done using the equals() method,
+ * not ==. The equals() method will try == first so
+ * in most cases the effect is the same.
+ *
+ * To use this class, it must be subclassed. For example:
+ *
+ * 
+ * public final class JavaVersionEnum extends ValuedEnum {
+ *   //standard enums for version of JVM
+ *   public static final int  JAVA1_0_VALUE  = 100;
+ *   public static final int  JAVA1_1_VALUE  = 110;
+ *   public static final int  JAVA1_2_VALUE  = 120;
+ *   public static final int  JAVA1_3_VALUE  = 130;
+ *   public static final JavaVersionEnum  JAVA1_0  = new JavaVersionEnum( "Java 1.0", JAVA1_0_VALUE );
+ *   public static final JavaVersionEnum  JAVA1_1  = new JavaVersionEnum( "Java 1.1", JAVA1_1_VALUE );
+ *   public static final JavaVersionEnum  JAVA1_2  = new JavaVersionEnum( "Java 1.2", JAVA1_2_VALUE );
+ *   public static final JavaVersionEnum  JAVA1_3  = new JavaVersionEnum( "Java 1.3", JAVA1_3_VALUE );
+ *
+ *   private JavaVersionEnum(String name, int value) {
+ *     super( name, value );
+ *   }
+ * 
+ *   public static JavaVersionEnum getEnum(String javaVersion) {
+ *     return (JavaVersionEnum) getEnum(JavaVersionEnum.class, javaVersion);
+ *   }
+ * 
+ *   public static JavaVersionEnum getEnum(int javaVersion) {
+ *     return (JavaVersionEnum) getEnum(JavaVersionEnum.class, javaVersion);
+ *   }
+ * 
+ *   public static Map getEnumMap() {
+ *     return getEnumMap(JavaVersionEnum.class);
+ *   }
+ * 
+ *   public static List getEnumList() {
+ *     return getEnumList(JavaVersionEnum.class);
+ *   }
+ * 
+ *   public static Iterator iterator() {
+ *     return iterator(JavaVersionEnum.class);
+ *   }
+ * }
+ * 
+ *
+ * The above class could then be used as follows:
+ *
+ * 
+ * public void doSomething(JavaVersion ver) {
+ *   switch (ver.getValue()) {
+ *     case JAVA1_0_VALUE:
+ *       // ...
+ *       break;
+ *     case JAVA1_1_VALUE:
+ *       // ...
+ *       break;
+ *     //...
+ *   }
+ * }
+ * 
+ *
+ * As shown, each enum has a name and a value. These can be accessed using
+ * getName and getValue.
+ *
+ * The getEnum and iterator methods are recommended.
+ * Unfortunately, Java restrictions require these to be coded as shown in each subclass.
+ * An alternative choice is to use the {@link EnumUtils} class.
+ *
+ * @author Apache Avalon project
+ * @author Stephen Colebourne
+ * @since 1.0
+ * @version $Id: ValuedEnum.java,v 1.1 2012/08/30 16:24:43 marcin Exp $
+ */
+public abstract class ValuedEnum extends Enum {
+    
+    /** Lang version 1.0.1 serial compatability */
+    private static final long serialVersionUID = -7129650521543789085L;
+    
+    /**
+     * The value contained in enum.
+     */
+    private final int iValue;
+
+    /**
+     * Constructor for enum item.
+     *
+     * @param name  the name of enum item
+     * @param value  the value of enum item
+     */
+    protected ValuedEnum(String name, int value) {
+        super(name);
+        iValue = value;
+    }
+
+    /**
+     * Gets an Enum object by class and value.
+     *
+     * This method loops through the list of Enum,
+     * thus if there are many Enums this will be
+     * slow.
+     * 
+     * @param enumClass  the class of the Enum to get
+     * @param value  the value of the Enum to get
+     * @return the enum object, or null if the enum does not exist
+     * @throws IllegalArgumentException if the enum class is null
+     */
+    protected static Enum getEnum(Class enumClass, int value) {
+        if (enumClass == null) {
+            throw new IllegalArgumentException("The Enum Class must not be null");
+        }
+        List list = Enum.getEnumList(enumClass);
+        for (Iterator it = list.iterator(); it.hasNext();) {
+            ValuedEnum enum = (ValuedEnum) it.next();
+            if (enum.getValue() == value) {
+                return enum;
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Get value of enum item.
+     *
+     * @return the enum item's value.
+     */
+    public final int getValue() {
+        return iValue;
+    }
+
+    /**
+     * Tests for order.
+     *
+     * The default ordering is numeric by value, but this
+     * can be overridden by subclasses.
+     * 
+     * @see java.lang.Comparable#compareTo(Object)
+     * @param other  the other object to compare to
+     * @return -ve if this is less than the other object, +ve if greater than,
+     *  0 of equal
+     * @throws ClassCastException if other is not an Enum
+     * @throws NullPointerException if other is null
+     */
+    public int compareTo(Object other) {
+        return iValue - ((ValuedEnum) other).iValue;
+    }
+
+    /**
+     * Human readable description of this Enum item.
+     *
+     * @return String in the form type[name=value], for example:
+     *  JavaVersion[Java 1.0=100]. Note that the package name is
+     *  stripped from the type name.
+     */
+    public String toString() {
+        if (iToString == null) {
+            String shortName = ClassUtils.getShortClassName(getEnumClass());
+            iToString = shortName + "[" + getName() + "=" + getValue() + "]";
+        }
+        return iToString;
+    }
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/enum/package.html
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/enum/package.html,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/enum/package.html	30 Aug 2012 16:24:44 -0000	1.1
@@ -0,0 +1,35 @@
+
+
+Provides an implementation of the C style 'enum' in the Java world.
+
+The classic example being an RGB color enumeration.
+
+public final class ColorEnum extends Enum {
+    public static final ColorEnum RED = new ColorEnum("Red");
+    public static final ColorEnum GREEN = new ColorEnum("Green");
+    public static final ColorEnum BLUE = new ColorEnum("Blue");
+
+    private ColorEnum(String color) {
+        super(color);
+    }
+
+    public static ColorEnum getEnum(String color) {
+        return (ColorEnum) getEnum(ColorEnum.class, color);
+    }
+
+    public static Map getEnumMap() {
+        return getEnumMap(ColorEnum.class);
+    }
+
+    public static List getEnumList() {
+        return getEnumList(ColorEnum.class);
+    }
+
+    public static Iterator iterator() {
+        return iterator(ColorEnum.class);
+    }
+}
+
+@since 1.0
+
+
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/exception/ExceptionUtils.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/exception/ExceptionUtils.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/exception/ExceptionUtils.java	30 Aug 2012 16:24:44 -0000	1.1
@@ -0,0 +1,716 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang.exception;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.lang.reflect.Field;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.sql.SQLException;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+import org.apache.commons.lang.ArrayUtils;
+import org.apache.commons.lang.StringUtils;
+import org.apache.commons.lang.SystemUtils;
+
+/**
+ * Provides utilities for manipulating and examining 
+ * Throwable objects.
+ *
+ * @author Daniel Rall
+ * @author Dmitri Plotnikov
+ * @author Stephen Colebourne
+ * @author Gary Gregory
+ * @author Pete Gieser
+ * @since 1.0
+ * @version $Id: ExceptionUtils.java,v 1.1 2012/08/30 16:24:44 marcin Exp $
+ */
+public class ExceptionUtils {
+    
+    /**
+     * Used when printing stack frames to denote the start of a
+     * wrapped exception.
+     *
+     * Package private for accessibility by test suite.
+     */
+    static final String WRAPPED_MARKER = " [wrapped] ";
+
+    /**
+     * The names of methods commonly used to access a wrapped exception.
+     */
+    private static String[] CAUSE_METHOD_NAMES = {
+        "getCause",
+        "getNextException",
+        "getTargetException",
+        "getException",
+        "getSourceException",
+        "getRootCause",
+        "getCausedByException",
+        "getNested"
+    };
+
+    /**
+     * The Method object for JDK1.4 getCause.
+     */
+    private static final Method THROWABLE_CAUSE_METHOD;
+    static {
+        Method getCauseMethod;
+        try {
+            getCauseMethod = Throwable.class.getMethod("getCause", null);
+        } catch (Exception e) {
+            getCauseMethod = null;
+        }
+        THROWABLE_CAUSE_METHOD = getCauseMethod;
+    }
+    
+    /**
+     * Public constructor allows an instance of ExceptionUtils
+     * to be created, although that is not normally necessary.
+     */
+    public ExceptionUtils() {
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Adds to the list of method names used in the search for Throwable
+     * objects.
+     * 
+     * @param methodName  the methodName to add to the list, null
+     *  and empty strings are ignored
+     * @since 2.0
+     */
+    public static void addCauseMethodName(String methodName) {
+        if (StringUtils.isNotEmpty(methodName)) {
+            List list = new ArrayList(Arrays.asList(CAUSE_METHOD_NAMES));
+            list.add(methodName);
+            CAUSE_METHOD_NAMES = (String[]) list.toArray(new String[list.size()]);
+        }
+    }
+
+    /**
+     * Introspects the Throwable to obtain the cause.
+     * 
+     * The method searches for methods with specific names that return a 
+     * Throwable object. This will pick up most wrapping exceptions,
+     * including those from JDK 1.4, and
+     * {@link org.apache.commons.lang.exception.NestableException NestableException}.
+     * The method names can be added to using {@link #addCauseMethodName(String)}.
+     *
+     * The default list searched for are:
+     * 
+     *  getCause() 
+     *  getNextException() 
+     *  getTargetException() 
+     *  getException() 
+     *  getSourceException() 
+     *  getRootCause() 
+     *  getCausedByException() 
+     *  getNested() 
+     * 
+     * 
+     * In the absence of any such method, the object is inspected for a
+     * detail field assignable to a Throwable.
+     * 
+     * If none of the above is found, returns null.
+     *
+     * @param throwable  the throwable to introspect for a cause, may be null
+     * @return the cause of the Throwable,
+     *  null if none found or null throwable input
+     */
+    public static Throwable getCause(Throwable throwable) {
+        return getCause(throwable, CAUSE_METHOD_NAMES);
+    }
+
+    /**
+     * Introspects the Throwable to obtain the cause.
+     * 
+     * 
+     * - Try known exception types.
 
+     * - Try the supplied array of method names.
 
+     * - Try the field 'detail'.
 
+     * 
+     * 
+     * A null set of method names means use the default set.
+     * A null in the set of method names will be ignored.
+     *
+     * @param throwable  the throwable to introspect for a cause, may be null
+     * @param methodNames  the method names, null treated as default set
+     * @return the cause of the Throwable,
+     *  null if none found or null throwable input
+     */
+    public static Throwable getCause(Throwable throwable, String[] methodNames) {
+        if (throwable == null) {
+            return null;
+        }
+        Throwable cause = getCauseUsingWellKnownTypes(throwable);
+        if (cause == null) {
+            if (methodNames == null) {
+                methodNames = CAUSE_METHOD_NAMES;
+            }
+            for (int i = 0; i < methodNames.length; i++) {
+                String methodName = methodNames[i];
+                if (methodName != null) {
+                    cause = getCauseUsingMethodName(throwable, methodName);
+                    if (cause != null) {
+                        break;
+                    }
+                }
+            }
+
+            if (cause == null) {
+                cause = getCauseUsingFieldName(throwable, "detail");
+            }
+        }
+        return cause;
+    }
+
+    /**
+     * Introspects the Throwable to obtain the root cause.
+     * 
+     * This method walks through the exception chain to the last element,
+     * "root" of the tree, using {@link #getCause(Throwable)}, and
+     * returns that exception.
+     *
+     * @param throwable  the throwable to get the root cause for, may be null
+     * @return the root cause of the Throwable,
+     *  null if none found or null throwable input
+     */
+    public static Throwable getRootCause(Throwable throwable) {
+        Throwable cause = getCause(throwable);
+        if (cause != null) {
+            throwable = cause;
+            while ((throwable = getCause(throwable)) != null) {
+                cause = throwable;
+            }
+        }
+        return cause;
+    }
+
+    /**
+     * Finds a Throwable for known types.
+     * 
+     * Uses instanceof checks to examine the exception,
+     * looking for well known types which could contain chained or
+     * wrapped exceptions.
+     *
+     * @param throwable  the exception to examine
+     * @return the wrapped exception, or null if not found
+     */
+    private static Throwable getCauseUsingWellKnownTypes(Throwable throwable) {
+        if (throwable instanceof Nestable) {
+            return ((Nestable) throwable).getCause();
+        } else if (throwable instanceof SQLException) {
+            return ((SQLException) throwable).getNextException();
+        } else if (throwable instanceof InvocationTargetException) {
+            return ((InvocationTargetException) throwable).getTargetException();
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Finds a Throwable by method name.
+     * 
+     * @param throwable  the exception to examine
+     * @param methodName  the name of the method to find and invoke
+     * @return the wrapped exception, or null if not found
+     */
+    private static Throwable getCauseUsingMethodName(Throwable throwable, String methodName) {
+        Method method = null;
+        try {
+            method = throwable.getClass().getMethod(methodName, null);
+        } catch (NoSuchMethodException ignored) {
+        } catch (SecurityException ignored) {
+        }
+
+        if (method != null && Throwable.class.isAssignableFrom(method.getReturnType())) {
+            try {
+                return (Throwable) method.invoke(throwable, ArrayUtils.EMPTY_OBJECT_ARRAY);
+            } catch (IllegalAccessException ignored) {
+            } catch (IllegalArgumentException ignored) {
+            } catch (InvocationTargetException ignored) {
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Finds a Throwable by field name.
+     * 
+     * @param throwable  the exception to examine
+     * @param fieldName  the name of the attribute to examine
+     * @return the wrapped exception, or null if not found
+     */
+    private static Throwable getCauseUsingFieldName(Throwable throwable, String fieldName) {
+        Field field = null;
+        try {
+            field = throwable.getClass().getField(fieldName);
+        } catch (NoSuchFieldException ignored) {
+        } catch (SecurityException ignored) {
+        }
+
+        if (field != null && Throwable.class.isAssignableFrom(field.getType())) {
+            try {
+                return (Throwable) field.get(throwable);
+            } catch (IllegalAccessException ignored) {
+            } catch (IllegalArgumentException ignored) {
+            }
+        }
+        return null;
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Checks if the Throwable class has a getCause method.
+     * 
+     * This is true for JDK 1.4 and above.
+     * 
+     * @return true if Throwable is nestable
+     * @since 2.0
+     */
+    public static boolean isThrowableNested() {
+        return (THROWABLE_CAUSE_METHOD != null);
+    }
+    
+    /**
+     * Checks whether this Throwable class can store a cause.
+     * 
+     * This method does not check whether it actually does store a cause.
+     *
+     * @param throwable  the Throwable to examine, may be null
+     * @return boolean true if nested otherwise false
+     * @since 2.0
+     */
+    public static boolean isNestedThrowable(Throwable throwable) {
+        if (throwable == null) {
+            return false;
+        }
+
+        if (throwable instanceof Nestable) {
+            return true;
+        } else if (throwable instanceof SQLException) {
+            return true;
+        } else if (throwable instanceof InvocationTargetException) {
+            return true;
+        } else if (isThrowableNested()) {
+            return true;
+        }
+
+        Class cls = throwable.getClass();
+        for (int i = 0, isize = CAUSE_METHOD_NAMES.length; i < isize; i++) {
+            try {
+                Method method = cls.getMethod(CAUSE_METHOD_NAMES[i], null);
+                if (method != null && Throwable.class.isAssignableFrom(method.getReturnType())) {
+                    return true;
+                }
+            } catch (NoSuchMethodException ignored) {
+            } catch (SecurityException ignored) {
+            }
+        }
+
+        try {
+            Field field = cls.getField("detail");
+            if (field != null) {
+                return true;
+            }
+        } catch (NoSuchFieldException ignored) {
+        } catch (SecurityException ignored) {
+        }
+
+        return false;
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * 
Counts the number of Throwable objects in the
+     * exception chain.
+     * 
+     * A throwable without cause will return 1.
+     * A throwable with one cause will return 2 and so on.
+     * A null throwable will return 0.
+     * 
+     * @param throwable  the throwable to inspect, may be null
+     * @return the count of throwables, zero if null input
+     */
+    public static int getThrowableCount(Throwable throwable) {
+        int count = 0;
+        while (throwable != null) {
+            count++;
+            throwable = ExceptionUtils.getCause(throwable);
+        }
+        return count;
+    }
+
+    /**
+     * Returns the list of Throwable objects in the
+     * exception chain.
+     * 
+     * A throwable without cause will return an array containing
+     * one element - the input throwable.
+     * A throwable with one cause will return an array containing
+     * two elements. - the input throwable and the cause throwable.
+     * A null throwable will return an array size zero.
+     *
+     * @param throwable  the throwable to inspect, may be null
+     * @return the array of throwables, never null
+     */
+    public static Throwable[] getThrowables(Throwable throwable) {
+        List list = new ArrayList();
+        while (throwable != null) {
+            list.add(throwable);
+            throwable = ExceptionUtils.getCause(throwable);
+        }
+        return (Throwable[]) list.toArray(new Throwable[list.size()]);
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Returns the (zero based) index of the first Throwable
+     * that matches the specified type in the exception chain.
+     * 
+     * A null throwable returns -1.
+     * A null type returns -1.
+     * No match in the chain returns -1.
+     *
+     * @param throwable  the throwable to inspect, may be null
+     * @param type  the type to search for
+     * @return the index into the throwable chain, -1 if no match or null input
+     */
+    public static int indexOfThrowable(Throwable throwable, Class type) {
+        return indexOfThrowable(throwable, type, 0);
+    }
+
+    /**
+     * Returns the (zero based) index of the first Throwable
+     * that matches the specified type in the exception chain from
+     * a specified index.
+     * 
+     * A null throwable returns -1.
+     * A null type returns -1.
+     * No match in the chain returns -1.
+     * A negative start index is treated as zero.
+     * A start index greater than the number of throwables returns -1.
+     *
+     * @param throwable  the throwable to inspect, may be null
+     * @param type  the type to search for
+     * @param fromIndex  the (zero based) index of the starting position,
+     *  negative treated as zero, larger than chain size returns -1
+     * @return the index into the throwable chain, -1 if no match or null input
+     */
+    public static int indexOfThrowable(Throwable throwable, Class type, int fromIndex) {
+        if (throwable == null) {
+            return -1;
+        }
+        if (fromIndex < 0) {
+            fromIndex = 0;
+        }
+        Throwable[] throwables = ExceptionUtils.getThrowables(throwable);
+        if (fromIndex >= throwables.length) {
+            return -1;
+        }
+        for (int i = fromIndex; i < throwables.length; i++) {
+            if (throwables[i].getClass().equals(type)) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Prints a compact stack trace for the root cause of a throwable
+     * to System.err.
+     * 
+     * The compact stack trace starts with the root cause and prints
+     * stack frames up to the place where it was caught and wrapped.
+     * Then it prints the wrapped exception and continues with stack frames
+     * until the wrapper exception is caught and wrapped again, etc.
+     *
+     * The method is equivalent to printStackTrace for throwables
+     * that don't have nested causes.
+     * 
+     * @param throwable  the throwable to output
+     * @since 2.0
+     */
+    public static void printRootCauseStackTrace(Throwable throwable) {
+        printRootCauseStackTrace(throwable, System.err);
+    }
+
+    /**
+     * Prints a compact stack trace for the root cause of a throwable.
+     *
+     * The compact stack trace starts with the root cause and prints
+     * stack frames up to the place where it was caught and wrapped.
+     * Then it prints the wrapped exception and continues with stack frames
+     * until the wrapper exception is caught and wrapped again, etc.
+     *
+     * The method is equivalent to printStackTrace for throwables
+     * that don't have nested causes.
+     * 
+     * @param throwable  the throwable to output, may be null
+     * @param stream  the stream to output to, may not be null
+     * @throws IllegalArgumentException if the stream is null
+     * @since 2.0
+     */
+    public static void printRootCauseStackTrace(Throwable throwable, PrintStream stream) {
+        if (throwable == null) {
+            return;
+        }
+        if (stream == null) {
+            throw new IllegalArgumentException("The PrintStream must not be null");
+        }
+        String trace[] = getRootCauseStackTrace(throwable);
+        for (int i = 0; i < trace.length; i++) {
+            stream.println(trace[i]);
+        }
+        stream.flush();
+    }
+
+    /**
+     * Prints a compact stack trace for the root cause of a throwable.
+     *
+     * The compact stack trace starts with the root cause and prints
+     * stack frames up to the place where it was caught and wrapped.
+     * Then it prints the wrapped exception and continues with stack frames
+     * until the wrapper exception is caught and wrapped again, etc.
+     *
+     * The method is equivalent to printStackTrace for throwables
+     * that don't have nested causes.
+     * 
+     * @param throwable  the throwable to output, may be null
+     * @param writer  the writer to output to, may not be null
+     * @throws IllegalArgumentException if the writer is null
+     * @since 2.0
+     */
+    public static void printRootCauseStackTrace(Throwable throwable, PrintWriter writer) {
+        if (throwable == null) {
+            return;
+        }
+        if (writer == null) {
+            throw new IllegalArgumentException("The PrintWriter must not be null");
+        }
+        String trace[] = getRootCauseStackTrace(throwable);
+        for (int i = 0; i < trace.length; i++) {
+            writer.println(trace[i]);
+        }
+        writer.flush();
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Creates a compact stack trace for the root cause of the supplied
+     * Throwable.
+     * 
+     * @param throwable  the throwable to examine, may be null
+     * @return an array of stack trace frames, never null
+     * @since 2.0
+     */
+    public static String[] getRootCauseStackTrace(Throwable throwable) {
+        if (throwable == null) {
+            return ArrayUtils.EMPTY_STRING_ARRAY;
+        }
+        Throwable throwables[] = getThrowables(throwable);
+        int count = throwables.length;
+        ArrayList frames = new ArrayList();
+        List nextTrace = getStackFrameList(throwables[count - 1]);
+        for (int i = count; --i >= 0;) {
+            List trace = nextTrace;
+            if (i != 0) {
+                nextTrace = getStackFrameList(throwables[i - 1]);
+                removeCommonFrames(trace, nextTrace);
+            }
+            if (i == count - 1) {
+                frames.add(throwables[i].toString());
+            } else {
+                frames.add(WRAPPED_MARKER + throwables[i].toString());
+            }
+            for (int j = 0; j < trace.size(); j++) {
+                frames.add(trace.get(j));
+            }
+        }
+        return (String[]) frames.toArray(new String[0]);
+    }
+
+    /**
+     * Removes common frames from the cause trace given the two stack traces.
+     * 
+     * @param causeFrames  stack trace of a cause throwable
+     * @param wrapperFrames  stack trace of a wrapper throwable
+     * @throws IllegalArgumentException if either argument is null
+     * @since 2.0
+     */
+    public static void removeCommonFrames(List causeFrames, List wrapperFrames) {
+        if (causeFrames == null || wrapperFrames == null) {
+            throw new IllegalArgumentException("The List must not be null");
+        }
+        int causeFrameIndex = causeFrames.size() - 1;
+        int wrapperFrameIndex = wrapperFrames.size() - 1;
+        while (causeFrameIndex >= 0 && wrapperFrameIndex >= 0) {
+            // Remove the frame from the cause trace if it is the same
+            // as in the wrapper trace
+            String causeFrame = (String) causeFrames.get(causeFrameIndex);
+            String wrapperFrame = (String) wrapperFrames.get(wrapperFrameIndex);
+            if (causeFrame.equals(wrapperFrame)) {
+                causeFrames.remove(causeFrameIndex);
+            }
+            causeFrameIndex--;
+            wrapperFrameIndex--;
+        }
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Gets the stack trace from a Throwable as a String.
+     *
+     * @param throwable  the Throwable to be examined
+     * @return the stack trace as generated by the exception's
+     *  printStackTrace(PrintWriter) method
+     */
+    public static String getStackTrace(Throwable throwable) {
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw, true);
+        throwable.printStackTrace(pw);
+        return sw.getBuffer().toString();
+    }
+
+    /**
+     * A way to get the entire nested stack-trace of an throwable.
+     *
+     * @param throwable  the Throwable to be examined
+     * @return the nested stack trace, with the root cause first
+     * @since 2.0
+     */
+    public static String getFullStackTrace(Throwable throwable) {
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw, true);
+        Throwable[] ts = getThrowables(throwable);
+        for (int i = 0; i < ts.length; i++) {
+            ts[i].printStackTrace(pw);
+            if (isNestedThrowable(ts[i])) {
+                break;
+            }
+        }
+        return sw.getBuffer().toString();
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Captures the stack trace associated with the specified
+     * Throwable object, decomposing it into a list of
+     * stack frames.
+     *
+     * @param throwable  the Throwable to exaamine, may be null
+     * @return an array of strings describing each stack frame, never null
+     */
+    public static String[] getStackFrames(Throwable throwable) {
+        if (throwable == null) {
+            return ArrayUtils.EMPTY_STRING_ARRAY;
+        }
+        return getStackFrames(getStackTrace(throwable));
+    }
+
+    /**
+     * Functionality shared between the
+     * getStackFrames(Throwable) methods of this and the
+     * {@link org.apache.commons.lang.exception.NestableDelegate}
+     * classes.
+     */
+    static String[] getStackFrames(String stackTrace) {
+        String linebreak = SystemUtils.LINE_SEPARATOR;
+        StringTokenizer frames = new StringTokenizer(stackTrace, linebreak);
+        List list = new LinkedList();
+        while (frames.hasMoreTokens()) {
+            list.add(frames.nextToken());
+        }
+        return (String[]) list.toArray(new String[list.size()]);
+    }
+
+    /**
+     * Produces a List of stack frames - the message
+     * is not included.
+     *
+     * This works in most cases - it will only fail if the exception
+     * message contains a line that starts with:
+     * "   at".
+     * 
+     * @param t is any throwable
+     * @return List of stack frames
+     */
+    static List getStackFrameList(Throwable t) {
+        String stackTrace = getStackTrace(t);
+        String linebreak = SystemUtils.LINE_SEPARATOR;
+        StringTokenizer frames = new StringTokenizer(stackTrace, linebreak);
+        List list = new LinkedList();
+        boolean traceStarted = false;
+        while (frames.hasMoreTokens()) {
+            String token = frames.nextToken();
+            // Determine if the line starts with at
+            int at = token.indexOf("at");
+            if (at != -1 && token.substring(0, at).trim().length() == 0) {
+                traceStarted = true;
+                list.add(token);
+            } else if (traceStarted) {
+                break;
+            }
+        }
+        return list;
+    }
+    
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/exception/Nestable.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/exception/Nestable.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/exception/Nestable.java	30 Aug 2012 16:24:44 -0000	1.1
@@ -0,0 +1,203 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang.exception;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+/**
+ * An interface to be implemented by {@link java.lang.Throwable}
+ * extensions which would like to be able to nest root exceptions
+ * inside themselves.
+ *
+ * @author Daniel Rall
+ * @author Kasper Nielsen
+ * @author Steven Caswell
+ * @author Pete Gieser
+ * @since 1.0
+ * @version $Id: Nestable.java,v 1.1 2012/08/30 16:24:44 marcin Exp $
+ */
+public interface Nestable {
+    
+    /**
+     * Returns the reference to the exception or error that caused the
+     * exception implementing the Nestable to be thrown.
+     *
+     * @return throwable that caused the original exception
+     */
+    public Throwable getCause();
+
+    /**
+     * Returns the error message of this and any nested
+     * Throwable.
+     *
+     * @return the error message
+     */
+    public String getMessage();
+
+    /**
+     * Returns the error message of the Throwable in the chain
+     * of Throwables at the specified index, numbererd from 0.
+     *
+     * @param index the index of the Throwable in the chain of
+     * Throwables
+     * @return the error message, or null if the Throwable at the
+     * specified index in the chain does not contain a message
+     * @throws IndexOutOfBoundsException if the index argument is
+     * negative or not less than the count of Throwables in the
+     * chain
+     */
+    public String getMessage(int index);
+
+    /**
+     * Returns the error message of this and any nested Throwables
+     * in an array of Strings, one element for each message. Any
+     * Throwable not containing a message is represented in the
+     * array by a null. This has the effect of cause the length of the returned
+     * array to be equal to the result of the {@link #getThrowableCount()}
+     * operation.
+     *
+     * @return the error messages
+     */
+    public String[] getMessages();
+
+    /**
+     * Returns the Throwable in the chain of
+     * Throwables at the specified index, numbererd from 0.
+     *
+     * @param index the index, numbered from 0, of the Throwable in
+     * the chain of Throwables
+     * @return the Throwable
+     * @throws IndexOutOfBoundsException if the index argument is
+     * negative or not less than the count of Throwables in the
+     * chain
+     */
+    public Throwable getThrowable(int index);
+
+    /**
+     * Returns the number of nested Throwables represented by
+     * this Nestable, including this Nestable.
+     *
+     * @return the throwable count
+     */
+    public int getThrowableCount();
+
+    /**
+     * Returns this Nestable and any nested Throwables
+     * in an array of Throwables, one element for each
+     * Throwable.
+     *
+     * @return the Throwables
+     */
+    public Throwable[] getThrowables();
+
+    /**
+     * Returns the index, numbered from 0, of the first occurrence of the
+     * specified type in the chain of Throwables, or -1 if the
+     * specified type is not found in the chain.
+     *
+     * @param type Class to be found
+     * @return index of the first occurrence of the type in the chain, or -1 if
+     * the type is not found
+     */
+    public int indexOfThrowable(Class type);
+
+    /**
+     * Returns the index, numbered from 0, of the first Throwable
+     * that matches the specified type in the chain of Throwables
+     * with an index greater than or equal to the specified index, or -1 if
+     * the type is not found.
+     *
+     * @param type Class to be found
+     * @param fromIndex the index, numbered from 0, of the starting position in
+     * the chain to be searched
+     * @return index of the first occurrence of the type in the chain, or -1 if
+     * the type is not found
+     * @throws IndexOutOfBoundsException if the fromIndex argument
+     * is negative or not less than the count of Throwables in the
+     * chain
+     */
+    public int indexOfThrowable(Class type, int fromIndex);
+
+    /**
+     * Prints the stack trace of this exception to the specified print
+     * writer.  Includes information from the exception, if any,
+     * which caused this exception.
+     *
+     * @param out PrintWriter to use for output.
+     */
+    public void printStackTrace(PrintWriter out);
+
+    /**
+     * Prints the stack trace of this exception to the specified print
+     * stream.  Includes inforamation from the exception, if any,
+     * which caused this exception.
+     *
+     * @param out PrintStream to use for output.
+     */
+    public void printStackTrace(PrintStream out);
+
+    /**
+     * Prints the stack trace for this exception only--root cause not
+     * included--using the provided writer.  Used by {@link
+     * org.apache.commons.lang.exception.NestableDelegate} to write
+     * individual stack traces to a buffer.  The implementation of
+     * this method should call
+     * super.printStackTrace(out); in most cases.
+     *
+     * @param out The writer to use.
+     */
+    public void printPartialStackTrace(PrintWriter out);
+    
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/exception/NestableDelegate.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/exception/NestableDelegate.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/exception/NestableDelegate.java	30 Aug 2012 16:24:44 -0000	1.1
@@ -0,0 +1,410 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang.exception;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+import java.io.Serializable;
+import java.io.StringWriter;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collections;
+import java.util.Iterator;
+import java.util.List;
+
+/**
+ * A shared implementation of the nestable exception functionality.
+ * 
+ * The code is shared between 
+ * {@link org.apache.commons.lang.exception.NestableError NestableError},
+ * {@link org.apache.commons.lang.exception.NestableException NestableException} and
+ * {@link org.apache.commons.lang.exception.NestableRuntimeException NestableRuntimeException}.
+ * 
+ * 
+ * @author Rafal Krzewski
+ * @author Daniel Rall
+ * @author Kasper Nielsen
+ * @author Steven Caswell
+ * @author Sean C. Sullivan
+ * @author Stephen Colebourne
+ * @since 1.0
+ * @version $Id: NestableDelegate.java,v 1.1 2012/08/30 16:24:44 marcin Exp $
+ */
+public class NestableDelegate implements Serializable {
+
+    /**
+     * Constructor error message.
+     */
+    private transient static final String MUST_BE_THROWABLE =
+        "The Nestable implementation passed to the NestableDelegate(Nestable) "
+            + "constructor must extend java.lang.Throwable";
+
+    /**
+     * Holds the reference to the exception or error that we're
+     * wrapping (which must be a {@link
+     * org.apache.commons.lang.exception.Nestable} implementation).
+     */
+    private Throwable nestable = null;
+    
+    /**
+     * Whether to print the stack trace top-down.
+     * This public flag may be set by calling code, typically in initialisation.
+     * @since 2.0
+     */
+    public static boolean topDown = true;
+    
+    /**
+     * Whether to trim the repeated stack trace.
+     * This public flag may be set by calling code, typically in initialisation.
+     * @since 2.0
+     */
+    public static boolean trimStackFrames = true;
+
+    /**
+     * Constructs a new NestableDelegate instance to manage the
+     * specified Nestable.
+     *
+     * @param nestable the Nestable implementation (must extend
+     * {@link java.lang.Throwable})
+     * @since 2.0
+     */
+    public NestableDelegate(Nestable nestable) {
+        if (nestable instanceof Throwable) {
+            this.nestable = (Throwable) nestable;
+        } else {
+            throw new IllegalArgumentException(MUST_BE_THROWABLE);
+        }
+    }
+
+    /**
+     * Returns the error message of the Throwable in the chain
+     * of Throwables at the specified index, numbererd from 0.
+     *
+     * @param index the index of the Throwable in the chain of
+     * Throwables
+     * @return the error message, or null if the Throwable at the
+     * specified index in the chain does not contain a message
+     * @throws IndexOutOfBoundsException if the index argument is
+     * negative or not less than the count of Throwables in the
+     * chain
+     * @since 2.0
+     */
+    public String getMessage(int index) {
+        Throwable t = this.getThrowable(index);
+        if (Nestable.class.isInstance(t)) {
+            return ((Nestable) t).getMessage(0);
+        } else {
+            return t.getMessage();
+        }
+    }
+
+    /**
+     * Returns the full message contained by the Nestable
+     * and any nested Throwables.
+     *
+     * @param baseMsg the base message to use when creating the full
+     * message. Should be generally be called via
+     * nestableHelper.getMessage(super.getMessage()),
+     * where super is an instance of {@link
+     * java.lang.Throwable}.
+     * @return The concatenated message for this and all nested
+     * Throwables
+     * @since 2.0
+     */
+    public String getMessage(String baseMsg) {
+        StringBuffer msg = new StringBuffer();
+        if (baseMsg != null) {
+            msg.append(baseMsg);
+        }
+
+        Throwable nestedCause = ExceptionUtils.getCause(this.nestable);
+        if (nestedCause != null) {
+            String causeMsg = nestedCause.getMessage();
+            if (causeMsg != null) {
+                if (baseMsg != null) {
+                    msg.append(": ");
+                }
+                msg.append(causeMsg);
+            }
+
+        }
+        return (msg.length() > 0 ? msg.toString() : null);
+    }
+
+    /**
+     * Returns the error message of this and any nested Throwables
+     * in an array of Strings, one element for each message. Any
+     * Throwable not containing a message is represented in the
+     * array by a null. This has the effect of cause the length of the returned
+     * array to be equal to the result of the {@link #getThrowableCount()}
+     * operation.
+     *
+     * @return the error messages
+     * @since 2.0
+     */
+    public String[] getMessages() {
+        Throwable[] throwables = this.getThrowables();
+        String[] msgs = new String[throwables.length];
+        for (int i = 0; i < throwables.length; i++) {
+            msgs[i] =
+                (Nestable.class.isInstance(throwables[i])
+                    ? ((Nestable) throwables[i]).getMessage(0)
+                    : throwables[i].getMessage());
+        }
+        return msgs;
+    }
+
+    /**
+     * Returns the Throwable in the chain of
+     * Throwables at the specified index, numbererd from 0.
+     *
+     * @param index the index, numbered from 0, of the Throwable in
+     * the chain of Throwables
+     * @return the Throwable
+     * @throws IndexOutOfBoundsException if the index argument is
+     * negative or not less than the count of Throwables in the
+     * chain
+     * @since 2.0
+     */
+    public Throwable getThrowable(int index) {
+        if (index == 0) {
+            return this.nestable;
+        }
+        Throwable[] throwables = this.getThrowables();
+        return throwables[index];
+    }
+
+    /**
+     * Returns the number of Throwables contained in the
+     * Nestable contained by this delegate.
+     *
+     * @return the throwable count
+     * @since 2.0
+     */
+    public int getThrowableCount() {
+        return ExceptionUtils.getThrowableCount(this.nestable);
+    }
+
+    /**
+     * Returns this delegate's Nestable and any nested
+     * Throwables in an array of Throwables, one
+     * element for each Throwable.
+     *
+     * @return the Throwables
+     * @since 2.0
+     */
+    public Throwable[] getThrowables() {
+        return ExceptionUtils.getThrowables(this.nestable);
+    }
+
+    /**
+     * Returns the index, numbered from 0, of the first Throwable
+     * that matches the specified type in the chain of Throwables
+     * held in this delegate's Nestable with an index greater than
+     * or equal to the specified index, or -1 if the type is not found.
+     *
+     * @param type Class to be found
+     * @param fromIndex the index, numbered from 0, of the starting position in
+     * the chain to be searched
+     * @return index of the first occurrence of the type in the chain, or -1 if
+     * the type is not found
+     * @throws IndexOutOfBoundsException if the fromIndex argument
+     * is negative or not less than the count of Throwables in the
+     * chain
+     * @since 2.0
+     */
+    public int indexOfThrowable(Class type, int fromIndex) {
+        if (fromIndex < 0) {
+            throw new IndexOutOfBoundsException("The start index was out of bounds: " + fromIndex);
+        }
+        Throwable[] throwables = ExceptionUtils.getThrowables(this.nestable);
+        if (fromIndex >= throwables.length) {
+            throw new IndexOutOfBoundsException("The start index was out of bounds: "
+                + fromIndex + " >= " + throwables.length);
+        }
+        for (int i = fromIndex; i < throwables.length; i++) {
+            if (throwables[i].getClass().equals(type)) {
+                return i;
+            }
+        }
+        return -1;
+    }
+
+    /**
+     * Prints the stack trace of this exception the the standar error
+     * stream.
+     */
+    public void printStackTrace() {
+        printStackTrace(System.err);
+    }
+
+    /**
+     * Prints the stack trace of this exception to the specified
+     * stream.
+     *
+     * @param out PrintStream to use for output.
+     * @see #printStackTrace(PrintWriter)
+     */
+    public void printStackTrace(PrintStream out) {
+        synchronized (out) {
+            PrintWriter pw = new PrintWriter(out, false);
+            printStackTrace(pw);
+            // Flush the PrintWriter before it's GC'ed.
+            pw.flush();
+        }
+    }
+
+    /**
+     * Prints the stack trace of this exception to the specified
+     * writer. If the Throwable class has a getCause
+     * method (i.e. running on jre1.4 or higher), this method just 
+     * uses Throwable's printStackTrace() method. Otherwise, generates
+     * the stack-trace, by taking into account the 'topDown' and 
+     * 'trimStackFrames' parameters. The topDown and trimStackFrames 
+     * are set to 'true' by default (produces jre1.4-like stack trace).
+     *
+     * @param out PrintWriter to use for output.
+     */
+    public void printStackTrace(PrintWriter out) {
+        Throwable throwable = this.nestable;
+        // if running on jre1.4 or higher, use default printStackTrace
+        if (ExceptionUtils.isThrowableNested()) {
+            if (throwable instanceof Nestable) {
+                ((Nestable)throwable).printPartialStackTrace(out);
+            } else {
+                throwable.printStackTrace(out);
+            }
+            return;
+        }
+
+        // generating the nested stack trace
+        List stacks = new ArrayList();
+        while (throwable != null) {
+            String[] st = getStackFrames(throwable);
+            stacks.add(st);
+            throwable = ExceptionUtils.getCause(throwable);
+        }
+
+        // If NOT topDown, reverse the stack
+        String separatorLine = "Caused by: ";
+        if (!topDown) {
+            separatorLine = "Rethrown as: ";
+            Collections.reverse(stacks);
+        }
+
+        // Remove the repeated lines in the stack
+        if (trimStackFrames) trimStackFrames(stacks);
+
+        synchronized (out) {
+            for (Iterator iter=stacks.iterator(); iter.hasNext();) {
+                String[] st = (String[]) iter.next();
+                for (int i=0, len=st.length; i < len; i++) {
+                    out.println(st[i]);
+                }
+                if (iter.hasNext())
+                    out.print(separatorLine);
+            }
+        }
+    }
+
+    /**
+     * Captures the stack trace associated with the specified
+     * Throwable object, decomposing it into a list of
+     * stack frames.
+     *
+     * @param t The Throwable.
+     * @return  An array of strings describing each stack frame.
+     * @since 2.0
+     */
+    protected String[] getStackFrames(Throwable t) {
+        StringWriter sw = new StringWriter();
+        PrintWriter pw = new PrintWriter(sw, true);
+
+        // Avoid infinite loop between decompose() and printStackTrace().
+        if (t instanceof Nestable) {
+            ((Nestable) t).printPartialStackTrace(pw);
+        } else {
+            t.printStackTrace(pw);
+        }
+        return ExceptionUtils.getStackFrames(sw.getBuffer().toString());
+    }
+    
+    /**
+     * Trims the stack frames. The first set is left untouched. The rest
+     * of the frames are truncated from the bottom by comparing with
+     * one just on top.
+     *
+     * @param stacks The list containing String[] elements
+     * @since 2.0
+     */
+    protected void trimStackFrames(List stacks) {
+         for (int size=stacks.size(), i=size-1; i > 0; i--) {
+             String[] curr = (String[]) stacks.get(i);
+             String[] next = (String[]) stacks.get(i-1); 
+             
+             List currList = new ArrayList(Arrays.asList(curr));
+             List nextList = new ArrayList(Arrays.asList(next));
+             ExceptionUtils.removeCommonFrames(currList, nextList);
+
+             int trimmed = curr.length - currList.size();
+             if (trimmed > 0) {
+                 currList.add("\t... "+trimmed+" more");
+                 stacks.set(
+                     i, 
+                     currList.toArray(new String[currList.size()])
+                 );
+             }
+         }
+     }
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/exception/NestableError.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/exception/NestableError.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/exception/NestableError.java	30 Aug 2012 16:24:44 -0000	1.1
@@ -0,0 +1,190 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang.exception;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+/**
+ * The base class of all errors which can contain other exceptions.
+ *
+ * @author Daniel Rall
+ * @see org.apache.commons.lang.exception.NestableException
+ * @since 1.0
+ * @version $Id: NestableError.java,v 1.1 2012/08/30 16:24:44 marcin Exp $
+ */
+public class NestableError extends Error implements Nestable {
+
+    /**
+     * The helper instance which contains much of the code which we
+     * delegate to.
+     */
+    protected NestableDelegate delegate = new NestableDelegate(this);
+
+    /**
+     * Holds the reference to the exception or error that caused
+     * this exception to be thrown.
+     */
+    private Throwable cause = null;
+
+    /**
+     * Constructs a new NestableError without specified
+     * detail message.
+     */
+    public NestableError() {
+        super();
+    }
+
+    /**
+     * Constructs a new NestableError with specified
+     * detail message.
+     *
+     * @param msg The error message.
+     */
+    public NestableError(String msg) {
+        super(msg);
+    }
+
+    /**
+     * Constructs a new NestableError with specified
+     * nested Throwable.
+     *
+     * @param cause the exception or error that caused this exception to be
+     * thrown
+     */
+    public NestableError(Throwable cause) {
+        super();
+        this.cause = cause;
+    }
+
+    /**
+     * Constructs a new NestableError with specified
+     * detail message and nested Throwable.
+     *
+     * @param msg    the error message
+     * @param cause  the exception or error that caused this exception to be
+     * thrown
+     */
+    public NestableError(String msg, Throwable cause) {
+        super(msg);
+        this.cause = cause;
+    }
+
+    public Throwable getCause() {
+        return cause;
+    }
+
+    /**
+     * Returns the detail message string of this throwable. If it was
+     * created with a null message, returns the following:
+     * (cause==null ? null : cause.toString()).
+     */
+    public String getMessage() {
+        if (super.getMessage() != null) {
+            return super.getMessage();
+        } else if (cause != null) {
+            return cause.toString();
+        } else {
+            return null;
+        }
+    }
+
+    public String getMessage(int index) {
+        if (index == 0) {
+            return super.getMessage();
+        } else {
+            return delegate.getMessage(index);
+        }
+    }
+
+    public String[] getMessages() {
+        return delegate.getMessages();
+    }
+
+    public Throwable getThrowable(int index) {
+        return delegate.getThrowable(index);
+    }
+
+    public int getThrowableCount() {
+        return delegate.getThrowableCount();
+    }
+
+    public Throwable[] getThrowables() {
+        return delegate.getThrowables();
+    }
+
+    public int indexOfThrowable(Class type) {
+        return delegate.indexOfThrowable(type, 0);
+    }
+
+    public int indexOfThrowable(Class type, int fromIndex) {
+        return delegate.indexOfThrowable(type, fromIndex);
+    }
+
+    public void printStackTrace() {
+        delegate.printStackTrace();
+    }
+
+    public void printStackTrace(PrintStream out) {
+        delegate.printStackTrace(out);
+    }
+
+    public void printStackTrace(PrintWriter out) {
+        delegate.printStackTrace(out);
+    }
+
+    public final void printPartialStackTrace(PrintWriter out) {
+        super.printStackTrace(out);
+    }
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/exception/NestableException.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/exception/NestableException.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/exception/NestableException.java	30 Aug 2012 16:24:44 -0000	1.1
@@ -0,0 +1,251 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang.exception;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+/**
+ * The base class of all exceptions which can contain other exceptions.
+ *
+ * It is intended to ease the debugging by carrying on the information
+ * about the exception which was caught and provoked throwing the
+ * current exception. Catching and rethrowing may occur multiple
+ * times, and provided that all exceptions except the first one
+ * are descendands of NestedException, when the
+ * exception is finally printed out using any of the 
+ * printStackTrace() methods, the stacktrace will contain
+ * the information about all exceptions thrown and caught on
+ * the way.
+ *  Running the following program
+ * 
+ *  1 import org.apache.commons.lang.exception.NestableException;
+ *  2
+ *  3 public class Test {
+ *  4     public static void main( String[] args ) {
+ *  5         try {
+ *  6             a();
+ *  7         } catch(Exception e) {
+ *  8             e.printStackTrace();
+ *  9         }
+ * 10      }
+ * 11
+ * 12      public static void a() throws Exception {
+ * 13          try {
+ * 14              b();
+ * 15          } catch(Exception e) {
+ * 16              throw new NestableException("foo", e);
+ * 17          }
+ * 18      }
+ * 19
+ * 20      public static void b() throws Exception {
+ * 21          try {
+ * 22              c();
+ * 23          } catch(Exception e) {
+ * 24              throw new NestableException("bar", e);
+ * 25          }
+ * 26      }
+ * 27
+ * 28      public static void c() throws Exception {
+ * 29          throw new Exception("baz");
+ * 30      }
+ * 31 }
+ * 
+ * Yields the following stacktrace:
+ * 
+ * org.apache.commons.lang.exception.NestableException: foo
+ *         at Test.a(Test.java:16)
+ *         at Test.main(Test.java:6)
+ * Caused by: org.apache.commons.lang.exception.NestableException: bar
+ *         at Test.b(Test.java:24)
+ *         at Test.a(Test.java:14)
+ *         ... 1 more
+ * Caused by: java.lang.Exception: baz
+ *         at Test.c(Test.java:29)
+ *         at Test.b(Test.java:22)
+ *         ... 2 more
+ * 
+ *
+ * @author Rafal Krzewski
+ * @author Daniel Rall
+ * @author Kasper Nielsen
+ * @author Steven Caswell
+ * @since 1.0
+ * @version $Id: NestableException.java,v 1.1 2012/08/30 16:24:44 marcin Exp $
+ */
+public class NestableException extends Exception implements Nestable {
+    
+    /**
+     * The helper instance which contains much of the code which we
+     * delegate to.
+     */
+    protected NestableDelegate delegate = new NestableDelegate(this);
+
+    /**
+     * Holds the reference to the exception or error that caused
+     * this exception to be thrown.
+     */
+    private Throwable cause = null;
+
+    /**
+     * Constructs a new NestableException without specified
+     * detail message.
+     */
+    public NestableException() {
+        super();
+    }
+
+    /**
+     * Constructs a new NestableException with specified
+     * detail message.
+     *
+     * @param msg The error message.
+     */
+    public NestableException(String msg) {
+        super(msg);
+    }
+
+    /**
+     * Constructs a new NestableException with specified
+     * nested Throwable.
+     *
+     * @param cause the exception or error that caused this exception to be
+     * thrown
+     */
+    public NestableException(Throwable cause) {
+        super();
+        this.cause = cause;
+    }
+
+    /**
+     * Constructs a new NestableException with specified
+     * detail message and nested Throwable.
+     *
+     * @param msg    the error message
+     * @param cause  the exception or error that caused this exception to be
+     * thrown
+     */
+    public NestableException(String msg, Throwable cause) {
+        super(msg);
+        this.cause = cause;
+    }
+
+    public Throwable getCause() {
+        return cause;
+    }
+
+    /**
+     * Returns the detail message string of this throwable. If it was
+     * created with a null message, returns the following:
+     * (cause==null ? null : cause.toString()).
+     */
+    public String getMessage() {
+        if (super.getMessage() != null) {
+            return super.getMessage();
+        } else if (cause != null) {
+            return cause.toString();
+        } else {
+            return null;
+        }
+    }
+
+    public String getMessage(int index) {
+        if (index == 0) {
+            return super.getMessage();
+        } else {
+            return delegate.getMessage(index);
+        }
+    }
+
+    public String[] getMessages() {
+        return delegate.getMessages();
+    }
+
+    public Throwable getThrowable(int index) {
+        return delegate.getThrowable(index);
+    }
+
+    public int getThrowableCount() {
+        return delegate.getThrowableCount();
+    }
+
+    public Throwable[] getThrowables() {
+        return delegate.getThrowables();
+    }
+
+    public int indexOfThrowable(Class type) {
+        return delegate.indexOfThrowable(type, 0);
+    }
+
+    public int indexOfThrowable(Class type, int fromIndex) {
+        return delegate.indexOfThrowable(type, fromIndex);
+    }
+
+    public void printStackTrace() {
+        delegate.printStackTrace();
+    }
+
+    public void printStackTrace(PrintStream out) {
+        delegate.printStackTrace(out);
+    }
+
+    public void printStackTrace(PrintWriter out) {
+        delegate.printStackTrace(out);
+    }
+
+    public final void printPartialStackTrace(PrintWriter out) {
+        super.printStackTrace(out);
+    }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/exception/NestableRuntimeException.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/exception/NestableRuntimeException.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/exception/NestableRuntimeException.java	30 Aug 2012 16:24:44 -0000	1.1
@@ -0,0 +1,195 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang.exception;
+
+import java.io.PrintStream;
+import java.io.PrintWriter;
+
+/**
+ * The base class of all runtime exceptions which can contain other
+ * exceptions.
+ *
+ * @see org.apache.commons.lang.exception.NestableException
+ * @author Rafal Krzewski
+ * @author Daniel Rall
+ * @author Kasper Nielsen
+ * @author Steven Caswell
+ * @since 1.0
+ * @version $Id: NestableRuntimeException.java,v 1.1 2012/08/30 16:24:44 marcin Exp $
+ */
+public class NestableRuntimeException extends RuntimeException implements Nestable {
+    
+    /**
+     * The helper instance which contains much of the code which we
+     * delegate to.
+     */
+    protected NestableDelegate delegate = new NestableDelegate(this);
+
+    /**
+     * Holds the reference to the exception or error that caused
+     * this exception to be thrown.
+     */
+    private Throwable cause = null;
+
+    /**
+     * Constructs a new NestableRuntimeException without specified
+     * detail message.
+     */
+    public NestableRuntimeException() {
+        super();
+    }
+
+    /**
+     * Constructs a new NestableRuntimeException with specified
+     * detail message.
+     *
+     * @param msg the error message
+     */
+    public NestableRuntimeException(String msg) {
+        super(msg);
+    }
+
+    /**
+     * Constructs a new NestableRuntimeException with specified
+     * nested Throwable.
+     *
+     * @param cause the exception or error that caused this exception to be
+     * thrown
+     */
+    public NestableRuntimeException(Throwable cause) {
+        super();
+        this.cause = cause;
+    }
+
+    /**
+     * Constructs a new NestableRuntimeException with specified
+     * detail message and nested Throwable.
+     *
+     * @param msg    the error message
+     * @param cause  the exception or error that caused this exception to be
+     * thrown
+     */
+    public NestableRuntimeException(String msg, Throwable cause) {
+        super(msg);
+        this.cause = cause;
+    }
+
+    public Throwable getCause() {
+        return cause;
+    }
+
+    /**
+     * Returns the detail message string of this throwable. If it was
+     * created with a null message, returns the following:
+     * (cause==null ? null : cause.toString()).
+     */
+    public String getMessage() {
+        if (super.getMessage() != null) {
+            return super.getMessage();
+        } else if (cause != null) {
+            return cause.toString();
+        } else {
+            return null;
+        }
+    }
+
+    public String getMessage(int index) {
+        if (index == 0) {
+            return super.getMessage();
+        } else {
+            return delegate.getMessage(index);
+        }
+    }
+
+    public String[] getMessages() {
+        return delegate.getMessages();
+    }
+
+    public Throwable getThrowable(int index) {
+        return delegate.getThrowable(index);
+    }
+
+    public int getThrowableCount() {
+        return delegate.getThrowableCount();
+    }
+
+    public Throwable[] getThrowables() {
+        return delegate.getThrowables();
+    }
+
+    public int indexOfThrowable(Class type) {
+        return delegate.indexOfThrowable(type, 0);
+    }
+
+    public int indexOfThrowable(Class type, int fromIndex) {
+        return delegate.indexOfThrowable(type, fromIndex);
+    }
+
+    public void printStackTrace() {
+        delegate.printStackTrace();
+    }
+
+    public void printStackTrace(PrintStream out) {
+        delegate.printStackTrace(out);
+    }
+
+    public void printStackTrace(PrintWriter out) {
+        delegate.printStackTrace(out);
+    }
+
+    public final void printPartialStackTrace(PrintWriter out) {
+        super.printStackTrace(out);
+    }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/exception/package.html
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/exception/package.html,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/exception/package.html	30 Aug 2012 16:24:44 -0000	1.1
@@ -0,0 +1,11 @@
+
+
+Provides JDK 1.4 style Nested Exception functionality for those on prior Java 
+versions.
+Includes a static utility to create version independent Nested 
+Exception which can handle JDK 1.4 Exceptions as well as others. 
+Lastly, {@link org.apache.commons.lang.exception.ExceptionUtils} 
+also contains Throwable manipulation and examination routines.
+@since 1.0
+
+
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/math/DoubleRange.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/math/DoubleRange.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/math/DoubleRange.java	30 Aug 2012 16:24:43 -0000	1.1
@@ -0,0 +1,448 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang.math;
+
+import java.io.Serializable;
+
+/**
+ * DoubleRange represents an inclusive range of doubles.
+ *
+ * @author Stephen Colebourne
+ * @since 2.0
+ * @version $Id: DoubleRange.java,v 1.1 2012/08/30 16:24:43 marcin Exp $
+ */
+public final class DoubleRange extends Range implements Serializable {
+    
+    private static final long serialVersionUID = 71849363892740L;
+
+    /**
+     * The minimum number in this range (inclusive).
+     */
+    private final double min;
+    /**
+     * The maximum number in this range (inclusive).
+     */
+    private final double max;
+    
+    /**
+     * Cached output minObject (class is immutable).
+     */
+    private transient Double minObject = null;
+    /**
+     * Cached output maxObject (class is immutable).
+     */
+    private transient Double maxObject = null;
+    /**
+     * Cached output hashCode (class is immutable).
+     */
+    private transient int hashCode = 0;
+    /**
+     * Cached output toString (class is immutable).
+     */
+    private transient String toString = null;
+    
+    /**
+     * Constructs a new DoubleRange using the specified
+     * number as both the minimum and maximum in this range.
+     *
+     * @param number  the number to use for this range
+     * @throws IllegalArgumentException if the number is NaN
+     */
+    public DoubleRange(double number) {
+        super();
+        if (Double.isNaN(number)) {
+            throw new IllegalArgumentException("The number must not be NaN");
+        }
+        this.min = number;
+        this.max = number;
+    }
+
+    /**
+     * Constructs a new DoubleRange using the specified
+     * number as both the minimum and maximum in this range.
+     *
+     * @param number  the number to use for this range, must not
+     *  be null
+     * @throws IllegalArgumentException if the number is null
+     * @throws IllegalArgumentException if the number is NaN
+     */
+    public DoubleRange(Number number) {
+        super();
+        if (number == null) {
+            throw new IllegalArgumentException("The number must not be null");
+        }
+        this.min = number.doubleValue();
+        this.max = number.doubleValue();
+        if (Double.isNaN(min) || Double.isNaN(max)) {
+            throw new IllegalArgumentException("The number must not be NaN");
+        }
+        if (number instanceof Double) {
+            this.minObject = (Double) number;
+            this.maxObject = (Double) number;
+        }
+    }
+
+    /**
+     * Constructs a new DoubleRange with the specified
+     * minimum and maximum numbers (both inclusive).
+     * 
+     * The arguments may be passed in the order (min,max) or (max,min). The
+     * getMinimum and getMaximum methods will return the correct values.
+     * 
+     * @param number1  first number that defines the edge of the range, inclusive
+     * @param number2  second number that defines the edge of the range, inclusive
+     * @throws IllegalArgumentException if either number is NaN
+     */
+    public DoubleRange(double number1, double number2) {
+        super();
+        if (Double.isNaN(number1) || Double.isNaN(number2)) {
+            throw new IllegalArgumentException("The numbers must not be NaN");
+        }
+        if (number2 < number1) {
+            this.min = number2;
+            this.max = number1;
+        } else {
+            this.min = number1;
+            this.max = number2;
+        }
+    }
+
+    /**
+     * Constructs a new DoubleRange with the specified
+     * minimum and maximum numbers (both inclusive).
+     * 
+     * The arguments may be passed in the order (min,max) or (max,min). The
+     * getMinimum and getMaximum methods will return the correct values.
+     *
+     * @param number1  first number that defines the edge of the range, inclusive
+     * @param number2  second number that defines the edge of the range, inclusive
+     * @throws IllegalArgumentException if either number is null
+     * @throws IllegalArgumentException if either number is NaN
+     */
+    public DoubleRange(Number number1, Number number2) {
+        super();
+        if (number1 == null || number2 == null) {
+            throw new IllegalArgumentException("The numbers must not be null");
+        }
+        double number1val = number1.doubleValue();
+        double number2val = number2.doubleValue();
+        if (Double.isNaN(number1val) || Double.isNaN(number2val)) {
+            throw new IllegalArgumentException("The numbers must not be NaN");
+        }
+        if (number2val < number1val) {
+            this.min = number2val;
+            this.max = number1val;
+            if (number2 instanceof Double) {
+                this.minObject = (Double) number2;
+            }
+            if (number1 instanceof Double) {
+                this.maxObject = (Double) number1;
+            }
+        } else {
+            this.min = number1val;
+            this.max = number2val;
+            if (number1 instanceof Double) {
+                this.minObject = (Double) number1;
+            }
+            if (number2 instanceof Double) {
+                this.maxObject = (Double) number2;
+            }
+        }
+    }
+
+    // Accessors
+    //--------------------------------------------------------------------
+
+    /**
+     * Returns the minimum number in this range.
+     *
+     * @return the minimum number in this range
+     */
+    public Number getMinimumNumber() {
+        if (minObject == null) {
+            minObject = new Double(min);            
+        }
+        return minObject;
+    }
+
+    /**
+     * Gets the minimum number in this range as a long.
+     * 
+     * This conversion can lose information for large values or decimals.
+     *
+     * @return the minimum number in this range
+     */
+    public long getMinimumLong() {
+        return (long) min;
+    }
+
+    /**
+     * Gets the minimum number in this range as a int.
+     * 
+     * This conversion can lose information for large values or decimals.
+     *
+     * @return the minimum number in this range
+     */
+    public int getMinimumInteger() {
+        return (int) min;
+    }
+
+    /**
+     * Gets the minimum number in this range as a double.
+     *
+     * @return the minimum number in this range
+     */
+    public double getMinimumDouble() {
+        return min;
+    }
+
+    /**
+     * Gets the minimum number in this range as a float.
+     * 
+     * This conversion can lose information for large values.
+     *
+     * @return the minimum number in this range
+     */
+    public float getMinimumFloat() {
+        return (float) min;
+    }
+
+    /**
+     * Returns the maximum number in this range.
+     *
+     * @return the maximum number in this range
+     */
+    public Number getMaximumNumber() {
+        if (maxObject == null) {
+            maxObject = new Double(max);            
+        }
+        return maxObject;
+    }
+
+    /**
+     * Gets the maximum number in this range as a long.
+     * 
+     * This conversion can lose information for large values or decimals.
+     *
+     * @return the maximum number in this range
+     */
+    public long getMaximumLong() {
+        return (long) max;
+    }
+
+    /**
+     * Gets the maximum number in this range as a int.
+     * 
+     * This conversion can lose information for large values or decimals.
+     *
+     * @return the maximum number in this range
+     */
+    public int getMaximumInteger() {
+        return (int) max;
+    }
+
+    /**
+     * Gets the maximum number in this range as a double.
+     *
+     * @return the maximum number in this range
+     */
+    public double getMaximumDouble() {
+        return max;
+    }
+
+    /**
+     * Gets the maximum number in this range as a float.
+     * 
+     * This conversion can lose information for large values.
+     *
+     * @return the maximum number in this range
+     */
+    public float getMaximumFloat() {
+        return (float) max;
+    }
+
+    // Tests
+    //--------------------------------------------------------------------
+    
+    /**
+     * Tests whether the specified number occurs within
+     * this range using double comparison.
+     * 
+     * null is handled and returns false.
+     *
+     * @param number  the number to test, may be null
+     * @return true if the specified number occurs within this range
+     */
+    public boolean containsNumber(Number number) {
+        if (number == null) {
+            return false;
+        }
+        return containsDouble(number.doubleValue());
+    }
+
+    /**
+     * Tests whether the specified double occurs within
+     * this range using double comparison.
+     * 
+     * This implementation overrides the superclass for performance as it is
+     * the most common case.
+     * 
+     * @param value  the double to test
+     * @return true if the specified number occurs within this
+     *  range by double comparison
+     */
+    public boolean containsDouble(double value) {
+        return (value >= min && value <= max);
+    }
+
+    // Range tests
+    //--------------------------------------------------------------------
+
+    /**
+     * Tests whether the specified range occurs entirely within this range
+     * using double comparison.
+     * 
+     * null is handled and returns false.
+     *
+     * @param range  the range to test, may be null
+     * @return true if the specified range occurs entirely within this range
+     * @throws IllegalArgumentException if the range is not of this type
+     */
+    public boolean containsRange(Range range) {
+        if (range == null) {
+            return false;
+        }
+        return containsDouble(range.getMinimumDouble())
+            && containsDouble(range.getMaximumDouble());
+    }
+
+    /**
+     * Tests whether the specified range overlaps with this range
+     * using double comparison.
+     * 
+     * null is handled and returns false.
+     *
+     * @param range  the range to test, may be null
+     * @return true if the specified range overlaps with this range
+     */
+    public boolean overlapsRange(Range range) {
+        if (range == null) {
+            return false;
+        }
+        return range.containsDouble(min)
+            || range.containsDouble(max)
+            || containsDouble(range.getMinimumDouble());
+    }
+
+    // Basics
+    //--------------------------------------------------------------------
+
+    /**
+     * Compares this range to another object to test if they are equal.
.
+     * 
+     * To be equal, the class, minimum and maximum must be equal.
+     *
+     * @param obj the reference object with which to compare
+     * @return true if this object is equal
+     */
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+        if (obj instanceof DoubleRange == false) {
+            return false;
+        }
+        DoubleRange range = (DoubleRange) obj;
+        return (Double.doubleToLongBits(min) == Double.doubleToLongBits(range.min) &&
+                Double.doubleToLongBits(max) == Double.doubleToLongBits(range.max));
+    }
+
+    /**
+     * Gets a hashCode for the range.
+     *
+     * @return a hash code value for this object
+     */
+    public int hashCode() {
+        if (hashCode == 0) {
+            hashCode = 17;
+            hashCode = 37 * hashCode + getClass().hashCode();
+            long lng = Double.doubleToLongBits(min);
+            hashCode = 37 * hashCode + ((int) (lng ^ (lng >> 32)));
+            lng = Double.doubleToLongBits(max);
+            hashCode = 37 * hashCode + ((int) (lng ^ (lng >> 32)));
+        }
+        return hashCode;
+    }
+
+    /**
+     * Gets the range as a String.
+     *
+     * The format of the String is 'Range[min,max]'.
+     *
+     * @return the String representation of this range
+     */
+    public String toString() {
+        if (toString == null) {
+            StringBuffer buf = new StringBuffer(32);
+            buf.append("Range[");
+            buf.append(min);
+            buf.append(',');
+            buf.append(max);
+            buf.append(']');
+            toString = buf.toString();
+        }
+        return toString;
+    }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/math/FloatRange.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/math/FloatRange.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/math/FloatRange.java	30 Aug 2012 16:24:43 -0000	1.1
@@ -0,0 +1,442 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang.math;
+
+import java.io.Serializable;
+
+/**
+ * FloatRange represents an inclusive range of floats.
+ *
+ * @author Stephen Colebourne
+ * @since 2.0
+ * @version $Id: FloatRange.java,v 1.1 2012/08/30 16:24:43 marcin Exp $
+ */
+public final class FloatRange extends Range implements Serializable {
+    
+    private static final long serialVersionUID = 71849363892750L;
+
+    /**
+     * The minimum number in this range (inclusive).
+     */
+    private final float min;
+    /**
+     * The maximum number in this range (inclusive).
+     */
+    private final float max;
+    
+    /**
+     * Cached output minObject (class is immutable).
+     */
+    private transient Float minObject = null;
+    /**
+     * Cached output maxObject (class is immutable).
+     */
+    private transient Float maxObject = null;
+    /**
+     * Cached output hashCode (class is immutable).
+     */
+    private transient int hashCode = 0;
+    /**
+     * Cached output toString (class is immutable).
+     */
+    private transient String toString = null;
+    
+    /**
+     * Constructs a new FloatRange using the specified
+     * number as both the minimum and maximum in this range.
+     *
+     * @param number  the number to use for this range
+     * @throws IllegalArgumentException if the number is NaN
+     */
+    public FloatRange(float number) {
+        super();
+        if (Float.isNaN(number)) {
+            throw new IllegalArgumentException("The number must not be NaN");
+        }
+        this.min = number;
+        this.max = number;
+    }
+
+    /**
+     * Constructs a new FloatRange using the specified
+     * number as both the minimum and maximum in this range.
+     *
+     * @param number  the number to use for this range, must not
+     *  be null
+     * @throws IllegalArgumentException if the number is null
+     * @throws IllegalArgumentException if the number is NaN
+     */
+    public FloatRange(Number number) {
+        super();
+        if (number == null) {
+            throw new IllegalArgumentException("The number must not be null");
+        }
+        this.min = number.floatValue();
+        this.max = number.floatValue();
+        if (Float.isNaN(min) || Float.isNaN(max)) {
+            throw new IllegalArgumentException("The number must not be NaN");
+        }
+        if (number instanceof Float) {
+            this.minObject = (Float) number;
+            this.maxObject = (Float) number;
+        }
+    }
+
+    /**
+     * Constructs a new FloatRange with the specified
+     * minimum and maximum numbers (both inclusive).
+     * 
+     * The arguments may be passed in the order (min,max) or (max,min). The
+     * getMinimum and getMaximum methods will return the correct values.
+     * 
+     * @param number1  first number that defines the edge of the range, inclusive
+     * @param number2  second number that defines the edge of the range, inclusive
+     * @throws IllegalArgumentException if either number is NaN
+     */
+    public FloatRange(float number1, float number2) {
+        super();
+        if (Float.isNaN(number1) || Float.isNaN(number2)) {
+            throw new IllegalArgumentException("The numbers must not be NaN");
+        }
+        if (number2 < number1) {
+            this.min = number2;
+            this.max = number1;
+        } else {
+            this.min = number1;
+            this.max = number2;
+        }
+    }
+
+    /**
+     * Constructs a new FloatRange with the specified
+     * minimum and maximum numbers (both inclusive).
+     * 
+     * The arguments may be passed in the order (min,max) or (max,min). The
+     * getMinimum and getMaximum methods will return the correct values.
+     *
+     * @param number1  first number that defines the edge of the range, inclusive
+     * @param number2  second number that defines the edge of the range, inclusive
+     * @throws IllegalArgumentException if either number is null
+     * @throws IllegalArgumentException if either number is NaN
+     */
+    public FloatRange(Number number1, Number number2) {
+        super();
+        if (number1 == null || number2 == null) {
+            throw new IllegalArgumentException("The numbers must not be null");
+        }
+        float number1val = number1.floatValue();
+        float number2val = number2.floatValue();
+        if (Float.isNaN(number1val) || Float.isNaN(number2val)) {
+            throw new IllegalArgumentException("The numbers must not be NaN");
+        }
+        if (number2val < number1val) {
+            this.min = number2val;
+            this.max = number1val;
+            if (number2 instanceof Float) {
+                this.minObject = (Float) number2;
+            }
+            if (number1 instanceof Float) {
+                this.maxObject = (Float) number1;
+            }
+        } else {
+            this.min = number1val;
+            this.max = number2val;
+            if (number1 instanceof Float) {
+                this.minObject = (Float) number1;
+            }
+            if (number2 instanceof Float) {
+                this.maxObject = (Float) number2;
+            }
+        }
+    }
+
+    // Accessors
+    //--------------------------------------------------------------------
+
+    /**
+     * Returns the minimum number in this range.
+     *
+     * @return the minimum number in this range
+     */
+    public Number getMinimumNumber() {
+        if (minObject == null) {
+            minObject = new Float(min);            
+        }
+        return minObject;
+    }
+
+    /**
+     * Gets the minimum number in this range as a long.
+     * 
+     * This conversion can lose information for large values or decimals.
+     *
+     * @return the minimum number in this range
+     */
+    public long getMinimumLong() {
+        return (long) min;
+    }
+
+    /**
+     * Gets the minimum number in this range as a int.
+     * 
+     * This conversion can lose information for large values or decimals.
+     *
+     * @return the minimum number in this range
+     */
+    public int getMinimumInteger() {
+        return (int) min;
+    }
+
+    /**
+     * Gets the minimum number in this range as a double.
+     *
+     * @return the minimum number in this range
+     */
+    public double getMinimumDouble() {
+        return min;
+    }
+
+    /**
+     * Gets the minimum number in this range as a float.
+     *
+     * @return the minimum number in this range
+     */
+    public float getMinimumFloat() {
+        return min;
+    }
+
+    /**
+     * Returns the maximum number in this range.
+     *
+     * @return the maximum number in this range
+     */
+    public Number getMaximumNumber() {
+        if (maxObject == null) {
+            maxObject = new Float(max);            
+        }
+        return maxObject;
+    }
+
+    /**
+     * Gets the maximum number in this range as a long.
+     * 
+     * This conversion can lose information for large values or decimals.
+     *
+     * @return the maximum number in this range
+     */
+    public long getMaximumLong() {
+        return (long) max;
+    }
+
+    /**
+     * Gets the maximum number in this range as a int.
+     * 
+     * This conversion can lose information for large values or decimals.
+     *
+     * @return the maximum number in this range
+     */
+    public int getMaximumInteger() {
+        return (int) max;
+    }
+
+    /**
+     * Gets the maximum number in this range as a double.
+     *
+     * @return the maximum number in this range
+     */
+    public double getMaximumDouble() {
+        return max;
+    }
+
+    /**
+     * Gets the maximum number in this range as a float.
+     *
+     * @return the maximum number in this range
+     */
+    public float getMaximumFloat() {
+        return max;
+    }
+
+    // Tests
+    //--------------------------------------------------------------------
+    
+    /**
+     * Tests whether the specified number occurs within
+     * this range using float comparison.
+     * 
+     * null is handled and returns false.
+     *
+     * @param number  the number to test, may be null
+     * @return true if the specified number occurs within this range
+     */
+    public boolean containsNumber(Number number) {
+        if (number == null) {
+            return false;
+        }
+        return containsFloat(number.floatValue());
+    }
+
+    /**
+     * Tests whether the specified float occurs within
+     * this range using float comparison.
+     * 
+     * This implementation overrides the superclass for performance as it is
+     * the most common case.
+     * 
+     * @param value  the float to test
+     * @return true if the specified number occurs within this
+     *  range by float comparison
+     */
+    public boolean containsFloat(float value) {
+        return (value >= min && value <= max);
+    }
+
+    // Range tests
+    //--------------------------------------------------------------------
+
+    /**
+     * Tests whether the specified range occurs entirely within this range
+     * using float comparison.
+     * 
+     * null is handled and returns false.
+     *
+     * @param range  the range to test, may be null
+     * @return true if the specified range occurs entirely within this range
+     * @throws IllegalArgumentException if the range is not of this type
+     */
+    public boolean containsRange(Range range) {
+        if (range == null) {
+            return false;
+        }
+        return containsFloat(range.getMinimumFloat()) &&
+               containsFloat(range.getMaximumFloat());
+    }
+
+    /**
+     * Tests whether the specified range overlaps with this range
+     * using float comparison.
+     * 
+     * null is handled and returns false.
+     *
+     * @param range  the range to test, may be null
+     * @return true if the specified range overlaps with this range
+     */
+    public boolean overlapsRange(Range range) {
+        if (range == null) {
+            return false;
+        }
+        return range.containsFloat(min) ||
+               range.containsFloat(max) || 
+               containsFloat(range.getMinimumFloat());
+    }
+
+    // Basics
+    //--------------------------------------------------------------------
+
+    /**
+     * Compares this range to another object to test if they are equal.
.
+     * 
+     * To be equal, the class, minimum and maximum must be equal.
+     *
+     * @param obj the reference object with which to compare
+     * @return true if this object is equal
+     */
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+        if (obj instanceof FloatRange == false) {
+            return false;
+        }
+        FloatRange range = (FloatRange) obj;
+        return (Float.floatToIntBits(min) == Float.floatToIntBits(range.min) &&
+                Float.floatToIntBits(max) == Float.floatToIntBits(range.max));
+    }
+
+    /**
+     * Gets a hashCode for the range.
+     *
+     * @return a hash code value for this object
+     */
+    public int hashCode() {
+        if (hashCode == 0) {
+            hashCode = 17;
+            hashCode = 37 * hashCode + getClass().hashCode();
+            hashCode = 37 * hashCode + Float.floatToIntBits(min);
+            hashCode = 37 * hashCode + Float.floatToIntBits(max);
+        }
+        return hashCode;
+    }
+
+    /**
+     * Gets the range as a String.
+     *
+     * The format of the String is 'Range[min,max]'.
+     *
+     * @return the String representation of this range
+     */
+    public String toString() {
+        if (toString == null) {
+            StringBuffer buf = new StringBuffer(32);
+            buf.append("Range[");
+            buf.append(min);
+            buf.append(',');
+            buf.append(max);
+            buf.append(']');
+            toString = buf.toString();
+        }
+        return toString;
+    }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/math/Fraction.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/math/Fraction.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/math/Fraction.java	30 Aug 2012 16:24:43 -0000	1.1
@@ -0,0 +1,794 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang.math;
+
+import java.io.Serializable;
+
+/**
+ * Fraction is a Number implementation that
+ * stores fractions accurately.
+ *
+ * This class is immutable, and interoperable with most methods that accept
+ * a Number.
+ *
+ * @author Travis Reeder
+ * @author Stephen Colebourne
+ * @author Tim O'Brien
+ * @author Pete Gieser
+ * @since 2.0
+ * @version $Id: Fraction.java,v 1.1 2012/08/30 16:24:43 marcin Exp $
+ */
+public final class Fraction extends Number implements Serializable, Comparable {
+
+    /** Serialization lock, Lang version 2.0 */
+    private static final long serialVersionUID = 65382027393090L;
+
+    /**
+     * Fraction representation of 0.
+     */
+    public static final Fraction ZERO = new Fraction(0, 1);
+    /**
+     * Fraction representation of 1.
+     */
+    public static final Fraction ONE = new Fraction(1, 1);
+    /**
+     * Fraction representation of 1/2.
+     */
+    public static final Fraction ONE_HALF = new Fraction(1, 2);
+    /**
+     * Fraction representation of 1/3.
+     */
+    public static final Fraction ONE_THIRD = new Fraction(1, 3);
+    /**
+     * Fraction representation of 2/3.
+     */
+    public static final Fraction TWO_THIRDS = new Fraction(2, 3);
+    /**
+     * Fraction representation of 1/4.
+     */
+    public static final Fraction ONE_QUARTER = new Fraction(1, 4);
+    /**
+     * Fraction representation of 2/4.
+     */
+    public static final Fraction TWO_QUARTERS = new Fraction(2, 4);
+    /**
+     * Fraction representation of 3/4.
+     */
+    public static final Fraction THREE_QUARTERS = new Fraction(3, 4);
+    /**
+     * Fraction representation of 1/5.
+     */
+    public static final Fraction ONE_FIFTH = new Fraction(1, 5);
+    /**
+     * Fraction representation of 2/5.
+     */
+    public static final Fraction TWO_FIFTHS = new Fraction(2, 5);
+    /**
+     * Fraction representation of 3/5.
+     */
+    public static final Fraction THREE_FIFTHS = new Fraction(3, 5);
+    /**
+     * Fraction representation of 4/5.
+     */
+    public static final Fraction FOUR_FIFTHS = new Fraction(4, 5);
+
+
+    /**
+     * The numerator number part of the fraction (the three in three sevenths).
+     */
+    private final int numerator;
+    /**
+     * The denominator number part of the fraction (the seven in three sevenths).
+     */
+    private final int denominator;
+
+    /**
+     * Cached output hashCode (class is immutable).
+     */
+    private transient int hashCode = 0;
+    /**
+     * Cached output toString (class is immutable).
+     */
+    private transient String toString = null;
+    /**
+     * Cached output toProperString (class is immutable).
+     */
+    private transient String toProperString = null;
+
+    /**
+     * Constructs a Fraction instance with the 2 parts
+     * of a fraction Y/Z.
+     *
+     * @param numerator  the numerator, for example the three in 'three sevenths'
+     * @param denominator  the denominator, for example the seven in 'three sevenths'
+     */
+    private Fraction(int numerator, int denominator) {
+        super();
+        this.numerator = numerator;
+        this.denominator = denominator;
+    }
+
+    /**
+     * Creates a Fraction instance with the 2 parts
+     * of a fraction Y/Z.
+     *
+     * Any negative signs are resolved to be on the numerator.
+     *
+     * @param numerator  the numerator, for example the three in 'three sevenths'
+     * @param denominator  the denominator, for example the seven in 'three sevenths'
+     * @return a new fraction instance
+     * @throws ArithmeticException if the denomiator is zero
+     */
+    public static Fraction getFraction(int numerator, int denominator) {
+        if (denominator == 0) {
+            throw new ArithmeticException("The denominator must not be zero");
+        }
+        if (denominator < 0) {
+            numerator = -numerator;
+            denominator = -denominator;
+        }
+        return new Fraction(numerator, denominator);
+    }
+
+    /**
+     * Creates a Fraction instance with the 3 parts
+     * of a fraction X Y/Z.
+     *
+     * The negative sign must be passed in on the whole number part.
+     *
+     * @param whole  the whole number, for example the one in 'one and three sevenths'
+     * @param numerator  the numerator, for example the three in 'one and three sevenths'
+     * @param denominator  the denominator, for example the seven in 'one and three sevenths'
+     * @return a new fraction instance
+     * @throws ArithmeticException if the denomiator is zero
+     * @throws ArithmeticException if the denomiator is negative
+     * @throws ArithmeticException if the numerator is negative
+     * @throws ArithmeticException if the resulting numerator exceeds 
+     *  Integer.MAX_VALUE
+     */
+    public static Fraction getFraction(int whole, int numerator, int denominator) {
+        if (denominator == 0) {
+            throw new ArithmeticException("The denominator must not be zero");
+        }
+        if (denominator < 0) {
+            throw new ArithmeticException("The denominator must not be negative");
+        }
+        if (numerator < 0) {
+            throw new ArithmeticException("The numerator must not be negative");
+        }
+        double numeratorValue = 0;
+        if (whole < 0) {
+            numeratorValue = (double) whole * denominator - numerator;
+        } else {
+            numeratorValue = (double) whole * denominator + numerator;
+        }
+        if (Math.abs(numeratorValue) > Integer.MAX_VALUE) {
+            throw new ArithmeticException("Numerator too large to represent as an Integer.");
+        }
+        return new Fraction((int) numeratorValue, denominator);
+    }
+
+    /**
+     * Creates a Fraction instance with the 2 parts
+     * of a fraction Y/Z.
+     *
+     * Any negative signs are resolved to be on the numerator.
+     *
+     * @param numerator  the numerator, for example the three in 'three sevenths'
+     * @param denominator  the denominator, for example the seven in 'three sevenths'
+     * @return a new fraction instance, with the numerator and denominator reduced
+     * @throws ArithmeticException if the denomiator is zero
+     */
+    public static Fraction getReducedFraction(int numerator, int denominator) {
+        if (denominator == 0) {
+            throw new ArithmeticException("The denominator must not be zero");
+        }
+        if (denominator < 0) {
+            numerator = -numerator;
+            denominator = -denominator;
+        }
+        int gcd = greatestCommonDivisor(Math.abs(numerator), denominator);
+        return new Fraction(numerator / gcd, denominator / gcd);
+    }
+
+    /**
+     * Creates a Fraction instance from a double value.
+     *
+     * This method uses the 
+     *  continued fraction algorithm, computing a maximum of
+     *  25 convergents and bounding the denominator by 10,000.
+     *
+     * @param value  the double value to convert
+     * @return a new fraction instance that is close to the value
+     * @throws ArithmeticException if |value| > Integer.MAX_VALUE 
+     *  or value = NaN
+     * @throws ArithmeticException if the calculated denomiator is zero
+     * @throws ArithmeticException if the the algorithm does not converge
+     */
+    public static Fraction getFraction(double value) {
+        int sign = (value < 0 ? -1 : 1);
+        value = Math.abs(value);
+        if (value  > Integer.MAX_VALUE || Double.isNaN(value)) {
+            throw new ArithmeticException
+                ("The value must not be greater than Integer.MAX_VALUE or NaN");
+        }
+        int wholeNumber = (int) value;
+        value -= wholeNumber;
+        
+        int numer0 = 0;  // the pre-previous
+        int denom0 = 1;  // the pre-previous
+        int numer1 = 1;  // the previous
+        int denom1 = 0;  // the previous
+        int numer2 = 0;  // the current, setup in calculation
+        int denom2 = 0;  // the current, setup in calculation
+        int a1 = (int) value;
+        int a2 = 0;
+        double x1 = 1;
+        double x2 = 0;
+        double y1 = value - a1;
+        double y2 = 0;
+        double delta1, delta2 = Double.MAX_VALUE;
+        double fraction;
+        int i = 1;
+//        System.out.println("---");
+        do {
+            delta1 = delta2;
+            a2 = (int) (x1 / y1);
+            x2 = y1;
+            y2 = x1 - a2 * y1;
+            numer2 = a1 * numer1 + numer0;
+            denom2 = a1 * denom1 + denom0;
+            fraction = (double) numer2 / (double) denom2;
+            delta2 = Math.abs(value - fraction);
+//            System.out.println(numer2 + " " + denom2 + " " + fraction + " " + delta2 + " " + y1);
+            a1 = a2;
+            x1 = x2;
+            y1 = y2;
+            numer0 = numer1;
+            denom0 = denom1;
+            numer1 = numer2;
+            denom1 = denom2;
+            i++;
+//            System.out.println(">>" + delta1 +" "+ delta2+" "+(delta1 > delta2)+" "+i+" "+denom2);
+        } while ((delta1 > delta2) && (denom2 <= 10000) && (denom2 > 0) && (i < 25));
+        if (i == 25) {
+            throw new ArithmeticException("Unable to convert double to fraction");
+        }
+        return getReducedFraction((numer0 + wholeNumber * denom0) * sign, denom0);
+    }
+
+    /**
+     * Creates a Fraction from a String.
+     *
+     * The formats accepted are:
+     *
+     * 
+     * 
+     *  double String containing a dot 
+     *  - 'X Y/Z'
 
+     *  - 'Y/Z'
 
+     * 
+     * and a .
+     *
+     * @param str  the string to parse, must not be null
+     * @return the new Fraction instance
+     * @throws IllegalArgumentException if the string is null
+     * @throws NumberFormatException if the number format is invalid
+     */
+    public static Fraction getFraction(String str) {
+        if (str == null) {
+            throw new IllegalArgumentException("The string must not be null");
+        }
+        // parse double format
+        int pos = str.indexOf('.');
+        if (pos >= 0) {
+            return getFraction(Double.parseDouble(str));
+        }
+
+        // parse X Y/Z format
+        pos = str.indexOf(' ');
+        if (pos > 0) {
+            int whole = Integer.parseInt(str.substring(0, pos));
+            str = str.substring(pos + 1);
+            pos = str.indexOf('/');
+            if (pos < 0) {
+                throw new NumberFormatException("The fraction could not be parsed as the format X Y/Z");
+            } else {
+                int denom = Integer.parseInt(str.substring(pos + 1));
+                return getFraction(
+                    Integer.parseInt(str.substring(0, pos)) + whole * denom,
+                    denom
+                );
+            }
+        }
+
+        // parse Y/Z format
+        pos = str.indexOf('/');
+        if (pos < 0) {
+            // simple whole number
+            return getFraction(Integer.parseInt(str), 1);
+        } else {
+            return getFraction(
+                Integer.parseInt(str.substring(0, pos)),
+                Integer.parseInt(str.substring(pos + 1))
+            );
+        }
+    }
+
+    // Accessors
+    //-------------------------------------------------------------------
+
+    /**
+     * Gets the numerator part of the fraction.
+     *
+     * This method may return a value greater than the denominator, an
+     * improper fraction, such as the seven in 7/4.
+     *
+     * @return the numerator fraction part
+     */
+    public int getNumerator() {
+        return numerator;
+    }
+
+    /**
+     * Gets the denominator part of the fraction.
+     *
+     * @return the denominator fraction part
+     */
+    public int getDenominator() {
+        return denominator;
+    }
+
+    /**
+     * Gets the proper numerator, always positive.
+     *
+     * An improper fraction 7/4 can be resolved into a proper one, 1 3/4.
+     * This method returns the 3 from the proper fraction.
+     *
+     * If the fraction is negative such as -7/4, it can be resolved into
+     * -1 3/4, so this method returns the positive proper numerator, 3.
+     *
+     * @return the numerator fraction part of a proper fraction, always positive
+     */
+    public int getProperNumerator() {
+        return Math.abs(numerator % denominator);
+    }
+
+    /**
+     * Gets the proper whole part of the fraction.
+     *
+     * An improper fraction 7/4 can be resolved into a proper one, 1 3/4.
+     * This method returns the 1 from the proper fraction.
+     *
+     * If the fraction is negative such as -7/4, it can be resolved into
+     * -1 3/4, so this method returns the positive whole part -1.
+     *
+     * @return the whole fraction part of a proper fraction, that includes the sign
+     */
+    public int getProperWhole() {
+        return numerator / denominator;
+    }
+
+    // Number methods
+    //-------------------------------------------------------------------
+
+    /**
+     * Gets the fraction as an int. This returns the whole number
+     * part of the fraction.
+     *
+     * @return the whole number fraction part
+     */
+    public int intValue() {
+        return numerator / denominator;
+    }
+
+    /**
+     * Gets the fraction as a long. This returns the whole number
+     * part of the fraction.
+     *
+     * @return the whole number fraction part
+     */
+    public long longValue() {
+        return (long) numerator / denominator;
+    }
+
+    /**
+     * Gets the fraction as a float. This calculates the fraction
+     * as the numerator divided by denominator.
+     *
+     * @return the fraction as a float
+     */
+    public float floatValue() {
+        return ((float) numerator) / ((float) denominator);
+    }
+
+    /**
+     * Gets the fraction as a double. This calculates the fraction
+     * as the numerator divided by denominator.
+     *
+     * @return the fraction as a double
+     */
+    public double doubleValue() {
+        return ((double) numerator) / ((double) denominator);
+    }
+
+    // Calculations
+    //-------------------------------------------------------------------
+
+    /**
+     * Reduce the fraction to the smallest values for the numerator and
+     * denominator, returning the result..
+     *
+     * @return a new reduce fraction instance, or this if no simplification possible
+     */
+    public Fraction reduce() {
+        int gcd = greatestCommonDivisor(Math.abs(numerator), denominator);
+        return Fraction.getFraction(numerator / gcd, denominator / gcd);
+    }
+
+    /**
+     * Gets a fraction that is the invert (1/fraction) of this one.
+     *
+     * The returned fraction is not reduced.
+     *
+     * @return a new fraction instance with the numerator and denominator inverted
+     * @throws ArithmeticException if the numerator is zero
+     */
+    public Fraction invert() {
+        if (numerator == 0) {
+            throw new ArithmeticException("Unable to invert a fraction with a zero numerator");
+        }
+        return getFraction(denominator, numerator);
+    }
+
+    /**
+     * Gets a fraction that is the negative (-fraction) of this one.
+     *
+     * The returned fraction is not reduced.
+     *
+     * @return a new fraction instance with the opposite signed numerator
+     */
+    public Fraction negate() {
+        return getFraction(-numerator, denominator);
+    }
+
+    /**
+     * Gets a fraction that is the positive equivalent of this one.
+     * More precisely: 
(fraction >= 0 ? this : -fraction)
+     *
+     * The returned fraction is not reduced.
+     *
+     * @return this if it is positive, or a new positive fraction
+     *  instance with the opposite signed numerator
+     */
+    public Fraction abs() {
+        if (numerator >= 0) {
+            return this;
+        }
+        return getFraction(-numerator, denominator);
+    }
+
+    /**
+     * Gets a fraction that is raised to the passed in power.
+     *
+     * The returned fraction is not reduced.
+     *
+     * @param power  the power to raise the fraction to
+     * @return this if the power is one, ONE if the power
+     * is zero (even if the fraction equals ZERO) or a new fraction instance 
+     * raised to the appropriate power
+     * @throws ArithmeticException if the resulting numerator or denominator exceeds
+     *  Integer.MAX_VALUE
+     */
+    public Fraction pow(int power) {
+        if (power == 1) {
+            return this;
+        } else if (power == 0) {
+            return ONE;
+        } else {
+            double denominatorValue = Math.pow(denominator, power);
+            double numeratorValue = Math.pow(numerator, power);
+            if (numeratorValue > Integer.MAX_VALUE || denominatorValue > Integer.MAX_VALUE) {
+                throw new ArithmeticException("Integer overflow");
+            }
+            if (power < 0) {
+                return getFraction((int) Math.pow(denominator, -power), 
+                    (int) Math.pow(numerator, -power));
+            }
+            return getFraction((int) Math.pow(numerator, power), 
+                (int) Math.pow(denominator, power));
+        }
+    }
+
+    /**
+     * Gets the greatest common divisor of two numbers.
+     *
+     * @param number1  a positive number
+     * @param number2  a positive number
+     * @return the greatest common divisor, never zero
+     */
+    private static int greatestCommonDivisor(int number1, int number2) {
+        int remainder = number1 % number2;
+        while (remainder != 0) {
+            number1 = number2;
+            number2 = remainder;
+            remainder = number1 % number2;
+        }
+        return number2;
+    }
+
+    // Arithmetic
+    //-------------------------------------------------------------------
+
+    /**
+     * Adds the value of this fraction to another, returning the result in 
+     * reduced form.
+     *
+     * @param fraction  the fraction to add, must not be null
+     * @return a Fraction instance with the resulting values
+     * @throws IllegalArgumentException if the fraction is null
+     * @throws ArithmeticException if the resulting numerator or denominator exceeds
+     *  Integer.MAX_VALUE
+     */
+    public Fraction add(Fraction fraction) {
+        if (fraction == null) {
+            throw new IllegalArgumentException("The fraction must not be null");
+        }
+        if (numerator == 0) {
+            return fraction;
+        }
+        if (fraction.numerator == 0) {
+            return this;
+        }     
+        // Compute lcd explicitly to limit overflow
+        int gcd = greatestCommonDivisor(Math.abs(fraction.denominator), Math.abs(denominator));
+        int thisResidue = denominator/gcd;
+        int thatResidue = fraction.denominator/gcd;
+        double denominatorValue = Math.abs((double) gcd * thisResidue * thatResidue);
+        double numeratorValue = (double) numerator * thatResidue + fraction.numerator * thisResidue;
+        if (Math.abs(numeratorValue) > Integer.MAX_VALUE || 
+            Math.abs(denominatorValue) > Integer.MAX_VALUE) {
+                throw new ArithmeticException("Integer overflow");
+        }
+        return Fraction.getReducedFraction((int) numeratorValue, (int) denominatorValue);
+    }
+
+    /**
+     * Subtracts the value of another fraction from the value of this one,
+     * returning the result in reduced form.
+     *
+     * @param fraction  the fraction to subtract, must not be null
+     * @return a Fraction instance with the resulting values
+     * @throws IllegalArgumentException if the fraction is null
+     * @throws ArithmeticException if the resulting numerator or denominator exceeds
+     *  Integer.MAX_VALUE
+     */
+    public Fraction subtract(Fraction fraction) {
+        if (fraction == null) {
+            throw new IllegalArgumentException("The fraction must not be null");
+        }
+        return add(fraction.negate());
+    }
+
+    /**
+     * Multiplies the value of this fraction by another, returning the result 
+     * in reduced form.
+     *
+     * @param fraction  the fraction to multipy by, must not be null
+     * @return a Fraction instance with the resulting values
+     * @throws IllegalArgumentException if the fraction is null
+     * @throws ArithmeticException if the resulting numerator or denominator exceeds
+     *  Integer.MAX_VALUE
+     */
+    public Fraction multiplyBy(Fraction fraction) {
+        if (fraction == null) {
+            throw new IllegalArgumentException("The fraction must not be null");
+        }
+        if (numerator == 0 || fraction.numerator == 0) {
+            return ZERO;
+        }
+        double numeratorValue = (double) numerator * fraction.numerator;
+        double denominatorValue = (double) denominator * fraction.denominator;
+        if (Math.abs(numeratorValue) > Integer.MAX_VALUE || 
+            Math.abs(denominatorValue) > Integer.MAX_VALUE) {
+                throw new ArithmeticException("Integer overflow");
+        }
+        return getReducedFraction((int) numeratorValue, (int) denominatorValue);
+    }
+
+    /**
+     * Divide the value of this fraction by another, returning the result 
+     * in reduced form.
+     *
+     * @param fraction  the fraction to divide by, must not be null
+     * @return a Fraction instance with the resulting values
+     * @throws IllegalArgumentException if the fraction is null
+     * @throws ArithmeticException if the fraction to divide by is zero
+     * @throws ArithmeticException if the resulting numerator or denominator exceeds
+     *  Integer.MAX_VALUE
+     */
+    public Fraction divideBy(Fraction fraction) {
+        if (fraction == null) {
+            throw new IllegalArgumentException("The fraction must not be null");
+        }
+        if (fraction.numerator == 0) {
+            throw new ArithmeticException("The fraction to divide by must not be zero");
+        }
+        if (numerator == 0) {
+            return ZERO;
+        }  
+        double numeratorValue = (double) numerator * fraction.denominator;
+        double denominatorValue = (double) denominator * fraction.numerator;
+        if (Math.abs(numeratorValue) > Integer.MAX_VALUE || 
+            Math.abs(denominatorValue) > Integer.MAX_VALUE) {
+                throw new ArithmeticException("Integer overflow");
+        }
+        return getReducedFraction((int) numeratorValue, (int) denominatorValue);
+    }
+
+    // Basics
+    //-------------------------------------------------------------------
+
+    /**
+     * Compares this fraction to another object to test if they are equal.
.
+     *
+     * To be equal, both values must be equal. Thus 2/4 is not equal to 1/2.
+     *
+     * @param obj the reference object with which to compare
+     * @return true if this object is equal
+     */
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+        if (obj instanceof Fraction == false) {
+            return false;
+        }
+        Fraction other = (Fraction) obj;
+        return (numerator == other.numerator &&
+                denominator == other.denominator);
+    }
+
+    /**
+     * Gets a hashCode for the fraction.
+     *
+     * @return a hash code value for this object
+     */
+    public int hashCode() {
+        if (hashCode == 0) {
+            hashCode = 17;
+            hashCode = 37 * hashCode + numerator;
+            hashCode = 37 * hashCode + denominator;
+        }
+        return hashCode;
+    }
+
+    /**
+     * Compares this object to another based on size.
+     *
+     * @param object  the object to compare to
+     * @return -1 if this is less, 0 if equal, +1 if greater
+     * @throws ClassCastException if the object is not a Fraction
+     * @throws NullPointerException if the object is null
+     */
+    public int compareTo(Object object) {
+        Fraction other = (Fraction) object;
+        if (numerator == other.numerator && denominator == other.denominator) {
+            return 0;
+        }
+
+        // otherwise see which is less
+        long first = (long) numerator * (long) other.denominator;
+        long second = (long) other.numerator * (long) denominator;
+        if (first == second) {
+            return 0;
+        } else if (first < second) {
+            return -1;
+        } else {
+            return 1;
+        }
+    }
+
+    /**
+     * Gets the fraction as a String.
+     *
+     * The format used is 'numerator/denominator' always.
+     *
+     * @return a String form of the fraction
+     */
+    public String toString() {
+        if (toString == null) {
+            toString = new StringBuffer(32)
+                .append(numerator)
+                .append('/')
+                .append(denominator).toString();
+        }
+        return toString;
+    }
+
+    /**
+     * 
Gets the fraction as a proper String in the format X Y/Z.
+     *
+     * The format used in 'wholeNumber numerator/denominator'.
+     * If the whole number is zero it will be ommitted. If the numerator is zero,
+     * only the whole number is returned.
+     *
+     * @return a String form of the fraction
+     */
+    public String toProperString() {
+        if (toProperString == null) {
+            if (numerator == 0) {
+                toProperString = "0";
+            } else if (numerator == denominator) {
+                toProperString = "1";
+            } else if (Math.abs(numerator) > denominator) {
+                int properNumerator = getProperNumerator();
+                if (properNumerator == 0) {
+                    toProperString = Integer.toString(getProperWhole());
+                } else {
+                    toProperString = new StringBuffer(32)
+                        .append(getProperWhole()).append(' ')
+                        .append(properNumerator).append('/')
+                        .append(denominator).toString();
+                }
+            } else {
+                toProperString = new StringBuffer(32)
+                    .append(numerator).append('/')
+                    .append(denominator).toString();
+            }
+        }
+        return toProperString;
+    }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/math/IntRange.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/math/IntRange.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/math/IntRange.java	30 Aug 2012 16:24:43 -0000	1.1
@@ -0,0 +1,416 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang.math;
+
+import java.io.Serializable;
+
+/**
+ * IntRange represents an inclusive range of ints.
+ *
+ * @author Stephen Colebourne
+ * @since 2.0
+ * @version $Id: IntRange.java,v 1.1 2012/08/30 16:24:43 marcin Exp $
+ */
+public final class IntRange extends Range implements Serializable {
+    
+    private static final long serialVersionUID = 71849363892730L;
+
+    /**
+     * The minimum number in this range (inclusive).
+     */
+    private final int min;
+    /**
+     * The maximum number in this range (inclusive).
+     */
+    private final int max;
+    
+    /**
+     * Cached output minObject (class is immutable).
+     */
+    private transient Integer minObject = null;
+    /**
+     * Cached output maxObject (class is immutable).
+     */
+    private transient Integer maxObject = null;
+    /**
+     * Cached output hashCode (class is immutable).
+     */
+    private transient int hashCode = 0;
+    /**
+     * Cached output toString (class is immutable).
+     */
+    private transient String toString = null;
+    
+    /**
+     * Constructs a new IntRange using the specified
+     * number as both the minimum and maximum in this range.
+     *
+     * @param number  the number to use for this range
+     */
+    public IntRange(int number) {
+        super();
+        this.min = number;
+        this.max = number;
+    }
+
+    /**
+     * Constructs a new IntRange using the specified
+     * number as both the minimum and maximum in this range.
+     *
+     * @param number  the number to use for this range, must not be null
+     * @throws IllegalArgumentException if the number is null
+     */
+    public IntRange(Number number) {
+        super();
+        if (number == null) {
+            throw new IllegalArgumentException("The number must not be null");
+        }
+        this.min = number.intValue();
+        this.max = number.intValue();
+        if (number instanceof Integer) {
+            this.minObject = (Integer) number;
+            this.maxObject = (Integer) number;
+        }
+    }
+
+    /**
+     * Constructs a new IntRange with the specified
+     * minimum and maximum numbers (both inclusive).
+     * 
+     * The arguments may be passed in the order (min,max) or (max,min). The
+     * getMinimum and getMaximum methods will return the correct values.
+     * 
+     * @param number1  first number that defines the edge of the range, inclusive
+     * @param number2  second number that defines the edge of the range, inclusive
+     */
+    public IntRange(int number1, int number2) {
+        super();
+        if (number2 < number1) {
+            this.min = number2;
+            this.max = number1;
+        } else {
+            this.min = number1;
+            this.max = number2;
+        }
+    }
+
+    /**
+     * Constructs a new IntRange with the specified
+     * minimum and maximum numbers (both inclusive).
+     * 
+     * The arguments may be passed in the order (min,max) or (max,min). The
+     * getMinimum and getMaximum methods will return the correct values.
+     *
+     * @param number1  first number that defines the edge of the range, inclusive
+     * @param number2  second number that defines the edge of the range, inclusive
+     * @throws IllegalArgumentException if either number is null
+     */
+    public IntRange(Number number1, Number number2) {
+        super();
+        if (number1 == null || number2 == null) {
+            throw new IllegalArgumentException("The numbers must not be null");
+        }
+        int number1val = number1.intValue();
+        int number2val = number2.intValue();
+        if (number2val < number1val) {
+            this.min = number2val;
+            this.max = number1val;
+            if (number2 instanceof Integer) {
+                this.minObject = (Integer) number2;
+            }
+            if (number1 instanceof Integer) {
+                this.maxObject = (Integer) number1;
+            }
+        } else {
+            this.min = number1val;
+            this.max = number2val;
+            if (number1 instanceof Integer) {
+                this.minObject = (Integer) number1;
+            }
+            if (number2 instanceof Integer) {
+                this.maxObject = (Integer) number2;
+            }
+        }
+    }
+
+    // Accessors
+    //--------------------------------------------------------------------
+
+    /**
+     * Returns the minimum number in this range.
+     *
+     * @return the minimum number in this range
+     */
+    public Number getMinimumNumber() {
+        if (minObject == null) {
+            minObject = new Integer(min);            
+        }
+        return minObject;
+    }
+
+    /**
+     * Gets the minimum number in this range as a long.
+     *
+     * @return the minimum number in this range
+     */
+    public long getMinimumLong() {
+        return min;
+    }
+
+    /**
+     * Gets the minimum number in this range as a int.
+     *
+     * @return the minimum number in this range
+     */
+    public int getMinimumInteger() {
+        return min;
+    }
+
+    /**
+     * Gets the minimum number in this range as a double.
+     *
+     * @return the minimum number in this range
+     */
+    public double getMinimumDouble() {
+        return min;
+    }
+
+    /**
+     * Gets the minimum number in this range as a float.
+     *
+     * @return the minimum number in this range
+     */
+    public float getMinimumFloat() {
+        return min;
+    }
+
+    /**
+     * Returns the maximum number in this range.
+     *
+     * @return the maximum number in this range
+     */
+    public Number getMaximumNumber() {
+        if (maxObject == null) {
+            maxObject = new Integer(max);            
+        }
+        return maxObject;
+    }
+
+    /**
+     * Gets the maximum number in this range as a long.
+     *
+     * @return the maximum number in this range
+     */
+    public long getMaximumLong() {
+        return max;
+    }
+
+    /**
+     * Gets the maximum number in this range as a int.
+     *
+     * @return the maximum number in this range
+     */
+    public int getMaximumInteger() {
+        return max;
+    }
+
+    /**
+     * Gets the maximum number in this range as a double.
+     *
+     * @return the maximum number in this range
+     */
+    public double getMaximumDouble() {
+        return max;
+    }
+
+    /**
+     * Gets the maximum number in this range as a float.
+     *
+     * @return the maximum number in this range
+     */
+    public float getMaximumFloat() {
+        return max;
+    }
+
+    // Tests
+    //--------------------------------------------------------------------
+    
+    /**
+     * Tests whether the specified number occurs within
+     * this range using int comparison.
+     * 
+     * null is handled and returns false.
+     *
+     * @param number  the number to test, may be null
+     * @return true if the specified number occurs within this range
+     */
+    public boolean containsNumber(Number number) {
+        if (number == null) {
+            return false;
+        }
+        return containsInteger(number.intValue());
+    }
+
+    /**
+     * Tests whether the specified int occurs within
+     * this range using int comparison.
+     * 
+     * This implementation overrides the superclass for performance as it is
+     * the most common case.
+     * 
+     * @param value  the int to test
+     * @return true if the specified number occurs within this
+     *  range by int comparison
+     */
+    public boolean containsInteger(int value) {
+        return (value >= min && value <= max);
+    }
+
+    // Range tests
+    //--------------------------------------------------------------------
+
+    /**
+     * Tests whether the specified range occurs entirely within this range
+     * using int comparison.
+     * 
+     * null is handled and returns false.
+     *
+     * @param range  the range to test, may be null
+     * @return true if the specified range occurs entirely within this range
+     * @throws IllegalArgumentException if the range is not of this type
+     */
+    public boolean containsRange(Range range) {
+        if (range == null) {
+            return false;
+        }
+        return containsInteger(range.getMinimumInteger()) &&
+               containsInteger(range.getMaximumInteger());
+    }
+
+    /**
+     * Tests whether the specified range overlaps with this range
+     * using int comparison.
+     * 
+     * null is handled and returns false.
+     *
+     * @param range  the range to test, may be null
+     * @return true if the specified range overlaps with this range
+     */
+    public boolean overlapsRange(Range range) {
+        if (range == null) {
+            return false;
+        }
+        return range.containsInteger(min) ||
+               range.containsInteger(max) || 
+               containsInteger(range.getMinimumInteger());
+    }
+
+    // Basics
+    //--------------------------------------------------------------------
+
+    /**
+     * Compares this range to another object to test if they are equal.
.
+     * 
+     * To be equal, the class, minimum and maximum must be equal.
+     *
+     * @param obj the reference object with which to compare
+     * @return true if this object is equal
+     */
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+        if (obj instanceof IntRange == false) {
+            return false;
+        }
+        IntRange range = (IntRange) obj;
+        return (min == range.min && max == range.max);
+    }
+
+    /**
+     * Gets a hashCode for the range.
+     *
+     * @return a hash code value for this object
+     */
+    public int hashCode() {
+        if (hashCode == 0) {
+            hashCode = 17;
+            hashCode = 37 * hashCode + getClass().hashCode();
+            hashCode = 37 * hashCode + min;
+            hashCode = 37 * hashCode + max;
+        }
+        return hashCode;
+    }
+
+    /**
+     * Gets the range as a String.
+     *
+     * The format of the String is 'Range[min,max]'.
+     *
+     * @return the String representation of this range
+     */
+    public String toString() {
+        if (toString == null) {
+            StringBuffer buf = new StringBuffer(32);
+            buf.append("Range[");
+            buf.append(min);
+            buf.append(',');
+            buf.append(max);
+            buf.append(']');
+            toString = buf.toString();
+        }
+        return toString;
+    }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/math/JVMRandom.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/math/JVMRandom.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/math/JVMRandom.java	30 Aug 2012 16:24:43 -0000	1.1
@@ -0,0 +1,186 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang.math;
+
+import java.util.Random;
+
+/**
+ * JVMRandom is a wrapper that supports all possible 
+ * Random methods via the {@link java.lang.Math#random()} method
+ * and its system-wide {@link Random} object.
+ * 
+ * @author Henri Yandell
+ * @since 2.0
+ * @version $Id: JVMRandom.java,v 1.1 2012/08/30 16:24:43 marcin Exp $
+ */
+public final class JVMRandom extends Random {
+
+    /**
+     * Ensures that only the constructor can call reseed.
+     */
+    private boolean constructed = false;
+
+    public JVMRandom() {
+        this.constructed = true;
+    }
+    
+    /**
+     * Unsupported in 2.0.
+     */
+    public synchronized void setSeed(long seed) {
+        if (this.constructed) {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+    /**
+     * Unsupported in 2.0.
+     */
+    public synchronized double nextGaussian() {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Unsupported in 2.0.
+     */
+    public void nextBytes(byte[] byteArray) {
+        throw new UnsupportedOperationException();
+    }
+
+    /**
+     * Returns the next pseudorandom, uniformly distributed int value
+     * from the Math.random() sequence.
+     *
+     * @return the random int
+     */
+    public int nextInt() {
+        return nextInt(Integer.MAX_VALUE);
+    }
+    /**
+     * Returns a pseudorandom, uniformly distributed int value between
+     * 0 (inclusive) and the specified value (exclusive), from
+     * the Math.random() sequence.
+     *
+     * @param n  the specified exclusive max-value
+     * @return the random int
+     * @throws IllegalArgumentException when n <= 0
+     */
+    public int nextInt(int n) {
+        if (n <= 0) {
+            throw new IllegalArgumentException(
+                "Upper bound for nextInt must be positive"
+            );
+        }
+        // TODO: check this cannot return 'n'
+        return (int)(Math.random() * n);
+    }
+    /**
+     * Returns the next pseudorandom, uniformly distributed long value
+     * from the Math.random() sequence.
+     * @return the random long
+     */
+    public long nextLong() {
+        // possible loss of precision?
+        return nextLong(Long.MAX_VALUE);
+    }
+
+
+    /**
+     * Returns a pseudorandom, uniformly distributed long value between
+     * 0 (inclusive) and the specified value (exclusive), from
+     * the Math.random() sequence.
+     *
+     * @param n  the specified exclusive max-value
+     * @return the random long
+     * @throws IllegalArgumentException when n <= 0
+     */
+    public static long nextLong(long n) {
+        if (n <= 0) {
+            throw new IllegalArgumentException(
+                "Upper bound for nextInt must be positive"
+            );
+        }
+        // TODO: check this cannot return 'n'
+        return (long)(Math.random() * n);
+     }
+
+    /**
+     * Returns the next pseudorandom, uniformly distributed boolean value
+     * from the Math.random() sequence.
+     *
+     * @return the random boolean
+     */
+    public boolean nextBoolean() {
+        return (Math.random() > 0.5);
+    }
+    /**
+     * Returns the next pseudorandom, uniformly distributed float value
+     * between 0.0 and 1.0 from the Math.random()
+     * sequence.
+     *
+     * @return the random float
+     */
+    public float nextFloat() {
+        return (float)Math.random();
+    }
+    /**
+     * Synonymous to the Math.random() call.
+     *
+     * @return the random double
+     */
+    public double nextDouble() {
+        return Math.random();
+    }
+    
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/math/LongRange.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/math/LongRange.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/math/LongRange.java	30 Aug 2012 16:24:43 -0000	1.1
@@ -0,0 +1,423 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang.math;
+
+import java.io.Serializable;
+
+/**
+ * LongRange represents an inclusive range of longs.
+ *
+ * @author Stephen Colebourne
+ * @since 2.0
+ * @version $Id: LongRange.java,v 1.1 2012/08/30 16:24:43 marcin Exp $
+ */
+public final class LongRange extends Range implements Serializable {
+    
+    private static final long serialVersionUID = 71849363892720L;
+
+    /**
+     * The minimum number in this range (inclusive).
+     */
+    private final long min;
+    /**
+     * The maximum number in this range (inclusive).
+     */
+    private final long max;
+    
+    /**
+     * Cached output minObject (class is immutable).
+     */
+    private transient Long minObject = null;
+    /**
+     * Cached output maxObject (class is immutable).
+     */
+    private transient Long maxObject = null;
+    /**
+     * Cached output hashCode (class is immutable).
+     */
+    private transient int hashCode = 0;
+    /**
+     * Cached output toString (class is immutable).
+     */
+    private transient String toString = null;
+    
+    /**
+     * Constructs a new LongRange using the specified
+     * number as both the minimum and maximum in this range.
+     *
+     * @param number  the number to use for this range
+     */
+    public LongRange(long number) {
+        super();
+        this.min = number;
+        this.max = number;
+    }
+
+    /**
+     * Constructs a new LongRange using the specified
+     * number as both the minimum and maximum in this range.
+     *
+     * @param number  the number to use for this range, must not
+     *  be null
+     * @throws IllegalArgumentException if the number is null
+     */
+    public LongRange(Number number) {
+        super();
+        if (number == null) {
+            throw new IllegalArgumentException("The number must not be null");
+        }
+        this.min = number.longValue();
+        this.max = number.longValue();
+        if (number instanceof Long) {
+            this.minObject = (Long) number;
+            this.maxObject = (Long) number;
+        }
+    }
+
+    /**
+     * Constructs a new LongRange with the specified
+     * minimum and maximum numbers (both inclusive).
+     * 
+     * The arguments may be passed in the order (min,max) or (max,min). The
+     * getMinimum and getMaximum methods will return the correct values.
+     * 
+     * @param number1  first number that defines the edge of the range, inclusive
+     * @param number2  second number that defines the edge of the range, inclusive
+     */
+    public LongRange(long number1, long number2) {
+        super();
+        if (number2 < number1) {
+            this.min = number2;
+            this.max = number1;
+        } else {
+            this.min = number1;
+            this.max = number2;
+        }
+    }
+
+    /**
+     * Constructs a new LongRange with the specified
+     * minimum and maximum numbers (both inclusive).
+     * 
+     * The arguments may be passed in the order (min,max) or (max,min). The
+     * getMinimum and getMaximum methods will return the correct values.
+     *
+     * @param number1  first number that defines the edge of the range, inclusive
+     * @param number2  second number that defines the edge of the range, inclusive
+     * @throws IllegalArgumentException if either number is null
+     */
+    public LongRange(Number number1, Number number2) {
+        super();
+        if (number1 == null || number2 == null) {
+            throw new IllegalArgumentException("The numbers must not be null");
+        }
+        long number1val = number1.longValue();
+        long number2val = number2.longValue();
+        if (number2val < number1val) {
+            this.min = number2val;
+            this.max = number1val;
+            if (number2 instanceof Long) {
+                this.minObject = (Long) number2;
+            }
+            if (number1 instanceof Long) {
+                this.maxObject = (Long) number1;
+            }
+        } else {
+            this.min = number1val;
+            this.max = number2val;
+            if (number1 instanceof Long) {
+                this.minObject = (Long) number1;
+            }
+            if (number2 instanceof Long) {
+                this.maxObject = (Long) number2;
+            }
+        }
+    }
+
+    // Accessors
+    //--------------------------------------------------------------------
+
+    /**
+     * Returns the minimum number in this range.
+     *
+     * @return the minimum number in this range
+     */
+    public Number getMinimumNumber() {
+        if (minObject == null) {
+            minObject = new Long(min);            
+        }
+        return minObject;
+    }
+
+    /**
+     * Gets the minimum number in this range as a long.
+     *
+     * @return the minimum number in this range
+     */
+    public long getMinimumLong() {
+        return min;
+    }
+
+    /**
+     * Gets the minimum number in this range as a int.
+     * 
+     * This conversion can lose information for large values.
+     *
+     * @return the minimum number in this range
+     */
+    public int getMinimumInteger() {
+        return (int) min;
+    }
+
+    /**
+     * Gets the minimum number in this range as a double.
+     * 
+     * This conversion can lose information for large values.
+     *
+     * @return the minimum number in this range
+     */
+    public double getMinimumDouble() {
+        return min;
+    }
+
+    /**
+     * Gets the minimum number in this range as a float.
+     * 
+     * This conversion can lose information for large values.
+     *
+     * @return the minimum number in this range
+     */
+    public float getMinimumFloat() {
+        return min;
+    }
+
+    /**
+     * Returns the maximum number in this range.
+     *
+     * @return the maximum number in this range
+     */
+    public Number getMaximumNumber() {
+        if (maxObject == null) {
+            maxObject = new Long(max);            
+        }
+        return maxObject;
+    }
+
+    /**
+     * Gets the maximum number in this range as a long.
+     *
+     * @return the maximum number in this range
+     */
+    public long getMaximumLong() {
+        return max;
+    }
+
+    /**
+     * Gets the maximum number in this range as a int.
+     * 
+     * This conversion can lose information for large values.
+     */
+    public int getMaximumInteger() {
+        return (int) max;
+    }
+
+    /**
+     * Gets the maximum number in this range as a double.
+     * 
+     * This conversion can lose information for large values.
+     */
+    public double getMaximumDouble() {
+        return max;
+    }
+
+    /**
+     * Gets the maximum number in this range as a float.
+     * 
+     * This conversion can lose information for large values.
+     */
+    public float getMaximumFloat() {
+        return max;
+    }
+
+    // Tests
+    //--------------------------------------------------------------------
+    
+    /**
+     * Tests whether the specified number occurs within
+     * this range using long comparison.
+     * 
+     * null is handled and returns false.
+     *
+     * @param number  the number to test, may be null
+     * @return true if the specified number occurs within this range
+     */
+    public boolean containsNumber(Number number) {
+        if (number == null) {
+            return false;
+        }
+        return containsLong(number.longValue());
+    }
+
+    /**
+     * Tests whether the specified long occurs within
+     * this range using long comparison.
+     * 
+     * This implementation overrides the superclass for performance as it is
+     * the most common case.
+     * 
+     * @param value  the long to test
+     * @return true if the specified number occurs within this
+     *  range by long comparison
+     */
+    public boolean containsLong(long value) {
+        return (value >= min && value <= max);
+    }
+
+    // Range tests
+    //--------------------------------------------------------------------
+
+    /**
+     * Tests whether the specified range occurs entirely within this range
+     * using long comparison.
+     * 
+     * null is handled and returns false.
+     *
+     * @param range  the range to test, may be null
+     * @return true if the specified range occurs entirely within this range
+     * @throws IllegalArgumentException if the range is not of this type
+     */
+    public boolean containsRange(Range range) {
+        if (range == null) {
+            return false;
+        }
+        return containsLong(range.getMinimumLong()) &&
+               containsLong(range.getMaximumLong());
+    }
+
+    /**
+     * Tests whether the specified range overlaps with this range
+     * using long comparison.
+     * 
+     * null is handled and returns false.
+     *
+     * @param range  the range to test, may be null
+     * @return true if the specified range overlaps with this range
+     */
+    public boolean overlapsRange(Range range) {
+        if (range == null) {
+            return false;
+        }
+        return range.containsLong(min) ||
+               range.containsLong(max) || 
+               containsLong(range.getMinimumLong());
+    }
+
+    // Basics
+    //--------------------------------------------------------------------
+
+    /**
+     * Compares this range to another object to test if they are equal.
.
+     * 
+     * To be equal, the class, minimum and maximum must be equal.
+     *
+     * @param obj the reference object with which to compare
+     * @return true if this object is equal
+     */
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+        if (obj instanceof LongRange == false) {
+            return false;
+        }
+        LongRange range = (LongRange) obj;
+        return (min == range.min && max == range.max);
+    }
+
+    /**
+     * Gets a hashCode for the range.
+     *
+     * @return a hash code value for this object
+     */
+    public int hashCode() {
+        if (hashCode == 0) {
+            hashCode = 17;
+            hashCode = 37 * hashCode + getClass().hashCode();
+            hashCode = 37 * hashCode + ((int) (min ^ (min >> 32)));
+            hashCode = 37 * hashCode + ((int) (max ^ (max >> 32)));
+        }
+        return hashCode;
+    }
+
+    /**
+     * Gets the range as a String.
+     *
+     * The format of the String is 'Range[min,max]'.
+     *
+     * @return the String representation of this range
+     */
+    public String toString() {
+        if (toString == null) {
+            StringBuffer buf = new StringBuffer(32);
+            buf.append("Range[");
+            buf.append(min);
+            buf.append(',');
+            buf.append(max);
+            buf.append(']');
+            toString = buf.toString();
+        }
+        return toString;
+    }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/math/NumberRange.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/math/NumberRange.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/math/NumberRange.java	30 Aug 2012 16:24:43 -0000	1.1
@@ -0,0 +1,274 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang.math;
+
+import java.io.Serializable;
+
+/**
+ * NumberRange represents an inclusive range of 
+ * {@link java.lang.Number} objects of the same type.
+ *
+ * @author Christopher Elkins
+ * @author Stephen Colebourne
+ * @since 2.0 (previously in org.apache.commons.lang)
+ * @version $Id: NumberRange.java,v 1.1 2012/08/30 16:24:43 marcin Exp $
+ */
+public final class NumberRange extends Range implements Serializable {
+    
+    private static final long serialVersionUID = 71849363892710L;
+
+    /**
+     * The minimum number in this range.
+     */
+    private final Number min;
+    /**
+     * The maximum number in this range.
+     */
+    private final Number max;
+    
+    /**
+     * Cached output hashCode (class is immutable).
+     */
+    private transient int hashCode = 0;
+    /**
+     * Cached output toString (class is immutable).
+     */
+    private transient String toString = null;
+
+    /**
+     * Constructs a new NumberRange using the specified
+     * number as both the minimum and maximum in this range.
+     *
+     * @param num the number to use for this range
+     * @throws IllegalArgumentException if the number is null
+     * @throws IllegalArgumentException if the number doesn't implement Comparable
+     * @throws IllegalArgumentException if the number is Double.NaN or Float.NaN
+     */
+    public NumberRange(Number num) {
+        if (num == null) {
+            throw new IllegalArgumentException("The number must not be null");
+        }
+        if (num instanceof Comparable == false) {
+            throw new IllegalArgumentException("The number must implement Comparable");
+        }
+        if (num instanceof Double && ((Double) num).isNaN()) {
+            throw new IllegalArgumentException("The number must not be NaN");
+        }
+        if (num instanceof Float && ((Float) num).isNaN()) {
+            throw new IllegalArgumentException("The number must not be NaN");
+        }
+
+        this.min = num;
+        this.max = num;
+    }
+
+    /**
+     * Constructs a new NumberRange with the specified
+     * minimum and maximum numbers (both inclusive).
+     * 
+     * The arguments may be passed in the order (min,max) or (max,min). The
+     * {@link #getMinimumNumber()} and {@link #getMaximumNumber()} methods will return the
+     * correct value.
+     * 
+     * This constructor is designed to be used with two Number
+     * objects of the same type. If two objects of different types are passed in,
+     * an exception is thrown.
+     *
+     * @param num1  first number that defines the edge of the range, inclusive
+     * @param num2  second number that defines the edge of the range, inclusive
+     * @throws IllegalArgumentException if either number is null
+     * @throws IllegalArgumentException if the numbers are of different types
+     * @throws IllegalArgumentException if the numbers don't implement Comparable
+     */
+    public NumberRange(Number num1, Number num2) {
+        if (num1 == null || num2 == null) {
+            throw new IllegalArgumentException("The numbers must not be null");
+        }
+        if (num1.getClass() != num2.getClass()) {
+            throw new IllegalArgumentException("The numbers must be of the same type");
+        }
+        if (num1 instanceof Comparable == false) {
+            throw new IllegalArgumentException("The numbers must implement Comparable");
+        }
+        if (num1 instanceof Double) {
+            if (((Double) num1).isNaN() || ((Double) num2).isNaN()) {
+                throw new IllegalArgumentException("The number must not be NaN");
+            }
+        } else if (num1 instanceof Float) {
+            if (((Float) num1).isNaN() || ((Float) num2).isNaN()) {
+                throw new IllegalArgumentException("The number must not be NaN");
+            }
+        }
+        
+        int compare = ((Comparable) num1).compareTo(num2);
+        if (compare == 0) {
+            this.min = num1;
+            this.max = num1;
+        } else if (compare > 0) {
+            this.min = num2;
+            this.max = num1;
+        } else {
+            this.min = num1;
+            this.max = num2;
+        }
+    }
+    
+    // Accessors
+    //--------------------------------------------------------------------
+
+    /**
+     * Returns the minimum number in this range.
+     *
+     * @return the minimum number in this range
+     */
+    public Number getMinimumNumber() {
+        return min;
+    }
+
+    /**
+     * Returns the maximum number in this range.
+     *
+     * @return the maximum number in this range
+     */
+    public Number getMaximumNumber() {
+        return max;
+    }
+
+    // Tests
+    //--------------------------------------------------------------------
+    
+    /**
+     * Tests whether the specified number occurs within
+     * this range.
+     * 
+     * null is handled and returns false.
+     *
+     * @param number  the number to test, may be null
+     * @return true if the specified number occurs within this range
+     * @throws IllegalArgumentException if the number is of a different type to the range
+     */
+    public boolean containsNumber(Number number) {
+        if (number == null) {
+            return false;
+        }
+        if (number.getClass() != min.getClass()) {
+            throw new IllegalArgumentException("The number must be of the same type as the range numbers");
+        }
+        int compareMin = ((Comparable) min).compareTo(number);
+        int compareMax = ((Comparable) max).compareTo(number);
+        return (compareMin <= 0 && compareMax >= 0);
+    }
+
+    // Range tests
+    //--------------------------------------------------------------------
+    // use Range implementations
+
+    // Basics
+    //--------------------------------------------------------------------
+
+    /**
+     * Compares this range to another object to test if they are equal.
.
+     * 
+     * To be equal, the class, minimum and maximum must be equal.
+     *
+     * @param obj the reference object with which to compare
+     * @return true if this object is equal
+     */
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        }
+        if (obj instanceof NumberRange == false) {
+            return false;
+        }
+        NumberRange range = (NumberRange) obj;
+        return min.equals(range.min) && max.equals(range.max);
+    }
+
+    /**
+     * Gets a hashCode for the range.
+     *
+     * @return a hash code value for this object
+     */
+    public int hashCode() {
+        if (hashCode == 0) {
+            hashCode = 17;
+            hashCode = 37 * hashCode + getClass().hashCode();
+            hashCode = 37 * hashCode + min.hashCode();
+            hashCode = 37 * hashCode + max.hashCode();
+        }
+        return hashCode;
+    }
+
+    /**
+     * Gets the range as a String.
+     *
+     * The format of the String is 'Range[min,max]'.
+     *
+     * @return the String representation of this range
+     */
+    public String toString() {
+        if (toString == null) {
+            StringBuffer buf = new StringBuffer(32);
+            buf.append("Range[");
+            buf.append(min);
+            buf.append(',');
+            buf.append(max);
+            buf.append(']');
+            toString = buf.toString();
+        }
+        return toString;
+    }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/math/NumberUtils.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/math/NumberUtils.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/math/NumberUtils.java	30 Aug 2012 16:24:43 -0000	1.1
@@ -0,0 +1,1224 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang.math;
+
+import java.math.BigDecimal;
+import java.math.BigInteger;
+
+import org.apache.commons.lang.StringUtils;
+
+/**
+ * Provides extra functionality for Java Number classes.
+ *
+ * @author Henri Yandell
+ * @author Rand McNeely
+ * @author Stephen Colebourne
+ * @author Steve Downey
+ * @author Eric Pugh
+ * @author Phil Steitz
+ * @author Matthew Hawthorne
+ * @author Gary Gregory
+ * @since 2.0
+ * @version $Id: NumberUtils.java,v 1.1 2012/08/30 16:24:43 marcin Exp $
+ */
+public class NumberUtils {
+    
+    /** Reusable Long constant for zero. */
+    public static final Long LONG_ZERO = new Long(0L);
+    /** Reusable Long constant for one. */
+    public static final Long LONG_ONE = new Long(1L);
+    /** Reusable Long constant for minus one. */
+    public static final Long LONG_MINUS_ONE = new Long(-1L);
+    /** Reusable Integer constant for zero. */
+    public static final Integer INTEGER_ZERO = new Integer(0);
+    /** Reusable Integer constant for one. */
+    public static final Integer INTEGER_ONE = new Integer(1);
+    /** Reusable Integer constant for minus one. */
+    public static final Integer INTEGER_MINUS_ONE = new Integer(-1);
+    /** Reusable Short constant for zero. */
+    public static final Short SHORT_ZERO = new Short((short) 0);
+    /** Reusable Short constant for one. */
+    public static final Short SHORT_ONE = new Short((short) 1);
+    /** Reusable Short constant for minus one. */
+    public static final Short SHORT_MINUS_ONE = new Short((short) -1);
+    /** Reusable Byte constant for zero. */
+    public static final Byte BYTE_ZERO = new Byte((byte) 0);
+    /** Reusable Byte constant for one. */
+    public static final Byte BYTE_ONE = new Byte((byte) 1);
+    /** Reusable Byte constant for minus one. */
+    public static final Byte BYTE_MINUS_ONE = new Byte((byte) -1);
+    /** Reusable Double constant for zero. */
+    public static final Double DOUBLE_ZERO = new Double(0.0d);
+    /** Reusable Double constant for one. */
+    public static final Double DOUBLE_ONE = new Double(1.0d);
+    /** Reusable Double constant for minus one. */
+    public static final Double DOUBLE_MINUS_ONE = new Double(-1.0d);
+    /** Reusable Float constant for zero. */
+    public static final Float FLOAT_ZERO = new Float(0.0f);
+    /** Reusable Float constant for one. */
+    public static final Float FLOAT_ONE = new Float(1.0f);
+    /** Reusable Float constant for minus one. */
+    public static final Float FLOAT_MINUS_ONE = new Float(-1.0f);
+
+    /**
+     * NumberUtils instances should NOT be constructed in standard programming.
+     * Instead, the class should be used as NumberUtils.stringToInt("6");.
+     *
+     * This constructor is public to permit tools that require a JavaBean instance
+     * to operate.
+     */
+    public NumberUtils() {
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Convert a String to an int, returning
+     * zero if the conversion fails.
+     *
+     * If the string is null, zero is returned.
+     * 
+     * @param str  the string to convert, may be null
+     * @return the int represented by the string, or zero if
+     *  conversion fails
+     */
+    public static int stringToInt(String str) {
+        return stringToInt(str, 0);
+    }
+
+    /**
+     * Convert a String to an int, returning a
+     * default value if the conversion fails.
+     *
+     * If the string is null, the default value is returned.
+     * 
+     * @param str  the string to convert, may be null
+     * @param defaultValue  the default value
+     * @return the int represented by the string, or the default if conversion fails
+     */
+    public static int stringToInt(String str, int defaultValue) {
+        try {
+            return Integer.parseInt(str);
+        } catch (NumberFormatException nfe) {
+            return defaultValue;
+        }
+    }
+
+    //-----------------------------------------------------------------------
+    // must handle Long, Float, Integer, Float, Short,
+    //                  BigDecimal, BigInteger and Byte
+    // useful methods:
+    // Byte.decode(String)
+    // Byte.valueOf(String,int radix)
+    // Byte.valueOf(String)
+    // Double.valueOf(String)
+    // Float.valueOf(String)
+    // new Float(String)
+    // Integer.valueOf(String,int radix)
+    // Integer.valueOf(String)
+    // Integer.decode(String)
+    // Integer.getInteger(String)
+    // Integer.getInteger(String,int val)
+    // Integer.getInteger(String,Integer val)
+    // new Integer(String)
+    // new Double(String)
+    // new Byte(String)
+    // new Long(String)
+    // Long.getLong(String)
+    // Long.getLong(String,int)
+    // Long.getLong(String,Integer)
+    // Long.valueOf(String,int)
+    // Long.valueOf(String)
+    // new Short(String)
+    // Short.decode(String)
+    // Short.valueOf(String,int)
+    // Short.valueOf(String)
+    // new BigDecimal(String)
+    // new BigInteger(String)
+    // new BigInteger(String,int radix)
+    // Possible inputs:
+    // 45 45.5 45E7 4.5E7 Hex Oct Binary xxxF xxxD xxxf xxxd
+    // plus minus everything. Prolly more. A lot are not separable.
+
+    /**
+     * Turns a string value into a java.lang.Number.
+     *
+     * First, the value is examined for a type qualifier on the end
+     * ('f','F','d','D','l','L').  If it is found, it starts 
+     * trying to create successively larger types from the type specified
+     * until one is found that can represent the value.
+     *
+     * If a type specifier is not found, it will check for a decimal point
+     * and then try successively larger types from Integer to
+     * BigInteger and from Float to
+     * BigDecimal.
+     *
+     * If the string starts with 0x or -0x, it
+     * will be interpreted as a hexadecimal integer.  Values with leading
+     * 0's will not be interpreted as octal.
+     *
+     * Returns null if the string is null.
+     *
+     * This method does not trim the input string, i.e., strings with leading
+     * or trailing spaces will generate NumberFormatExceptions.
+     *
+     * @param str  String containing a number, may be null
+     * @return Number created from the string
+     * @throws NumberFormatException if the value cannot be converted
+     */
+    public static Number createNumber(String str) throws NumberFormatException {
+        if (str == null) {
+            return null;
+        }
+        if (StringUtils.isBlank(str)) {
+            throw new NumberFormatException("A blank string is not a valid number");
+        }  
+        if (str.startsWith("--")) {
+            // this is protection for poorness in java.lang.BigDecimal.
+            // it accepts this as a legal value, but it does not appear 
+            // to be in specification of class. OS X Java parses it to 
+            // a wrong value.
+            return null;
+        }
+        if (str.startsWith("0x") || str.startsWith("-0x")) {
+            return createInteger(str);
+        }   
+        char lastChar = str.charAt(str.length() - 1);
+        String mant;
+        String dec;
+        String exp;
+        int decPos = str.indexOf('.');
+        int expPos = str.indexOf('e') + str.indexOf('E') + 1;
+
+        if (decPos > -1) {
+
+            if (expPos > -1) {
+                if (expPos < decPos) {
+                    throw new NumberFormatException(str + " is not a valid number.");
+                }
+                dec = str.substring(decPos + 1, expPos);
+            } else {
+                dec = str.substring(decPos + 1);
+            }
+            mant = str.substring(0, decPos);
+        } else {
+            if (expPos > -1) {
+                mant = str.substring(0, expPos);
+            } else {
+                mant = str;
+            }
+            dec = null;
+        }
+        if (!Character.isDigit(lastChar)) {
+            if (expPos > -1 && expPos < str.length() - 1) {
+                exp = str.substring(expPos + 1, str.length() - 1);
+            } else {
+                exp = null;
+            }
+            //Requesting a specific type..
+            String numeric = str.substring(0, str.length() - 1);
+            boolean allZeros = isAllZeros(mant) && isAllZeros(exp);
+            switch (lastChar) {
+                case 'l' :
+                case 'L' :
+                    if (dec == null
+                        && exp == null
+                        && isDigits(numeric.substring(1))
+                        && (numeric.charAt(0) == '-' || Character.isDigit(numeric.charAt(0)))) {
+                        try {
+                            return createLong(numeric);
+                        } catch (NumberFormatException nfe) {
+                            //Too big for a long
+                        }
+                        return createBigInteger(numeric);
+
+                    }
+                    throw new NumberFormatException(str + " is not a valid number.");
+                case 'f' :
+                case 'F' :
+                    try {
+                        Float f = NumberUtils.createFloat(numeric);
+                        if (!(f.isInfinite() || (f.floatValue() == 0.0F && !allZeros))) {
+                            //If it's too big for a float or the float value = 0 and the string
+                            //has non-zeros in it, then float doens't have the presision we want
+                            return f;
+                        }
+
+                    } catch (NumberFormatException nfe) {
+                    }
+                    //Fall through
+                case 'd' :
+                case 'D' :
+                    try {
+                        Double d = NumberUtils.createDouble(numeric);
+                        if (!(d.isInfinite() || (d.floatValue() == 0.0D && !allZeros))) {
+                            return d;
+                        }
+                    } catch (NumberFormatException nfe) {
+                    }
+                    try {
+                        return createBigDecimal(numeric);
+                    } catch (NumberFormatException e) {
+                    }
+                    //Fall through
+                default :
+                    throw new NumberFormatException(str + " is not a valid number.");
+
+            }
+        } else {
+            //User doesn't have a preference on the return type, so let's start
+            //small and go from there...
+            if (expPos > -1 && expPos < str.length() - 1) {
+                exp = str.substring(expPos + 1, str.length());
+            } else {
+                exp = null;
+            }
+            if (dec == null && exp == null) {
+                //Must be an int,long,bigint
+                try {
+                    return createInteger(str);
+                } catch (NumberFormatException nfe) {
+                }
+                try {
+                    return createLong(str);
+                } catch (NumberFormatException nfe) {
+                }
+                return createBigInteger(str);
+
+            } else {
+                //Must be a float,double,BigDec
+                boolean allZeros = isAllZeros(mant) && isAllZeros(exp);
+                try {
+                    Float f = createFloat(str);
+                    if (!(f.isInfinite() || (f.floatValue() == 0.0F && !allZeros))) {
+                        return f;
+                    }
+                } catch (NumberFormatException nfe) {
+                }
+                try {
+                    Double d = createDouble(str);
+                    if (!(d.isInfinite() || (d.doubleValue() == 0.0D && !allZeros))) {
+                        return d;
+                    }
+                } catch (NumberFormatException nfe) {
+                }
+
+                return createBigDecimal(str);
+
+            }
+        }
+    }
+
+    /**
+     * Utility method for {@link #createNumber(java.lang.String)}.
+     *
+     * Returns true if s is null.
+     * 
+     * @param str  the String to check
+     * @return if it is all zeros or null
+     */
+    private static boolean isAllZeros(String str) {
+        if (str == null) {
+            return true;
+        }
+        for (int i = str.length() - 1; i >= 0; i--) {
+            if (str.charAt(i) != '0') {
+                return false;
+            }
+        }
+        return str.length() > 0;
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Convert a String to a Float.
+     *
+     * Returns null if the string is null.
+     * 
+     * @param str  a String to convert, may be null
+     * @return converted Float
+     * @throws NumberFormatException if the value cannot be converted
+     */
+    public static Float createFloat(String str) {
+        if (str == null) {
+            return null;
+        }
+        return Float.valueOf(str);
+    }
+
+    /**
+     * Convert a String to a Double.
+     * 
+     * Returns null if the string is null.
+     *
+     * @param str  a String to convert, may be null
+     * @return converted Double
+     * @throws NumberFormatException if the value cannot be converted
+     */
+    public static Double createDouble(String str) {
+        if (str == null) {
+            return null;
+        }
+        return Double.valueOf(str);
+    }
+
+    /**
+     * Convert a String to a Integer, handling
+     * hex and octal notations.
+     *
+     * Returns null if the string is null.
+     * 
+     * @param str  a String to convert, may be null
+     * @return converted Integer
+     * @throws NumberFormatException if the value cannot be converted
+     */
+    public static Integer createInteger(String str) {
+        if (str == null) {
+            return null;
+        }
+        // decode() handles 0xAABD and 0777 (hex and octal) as well.
+        return Integer.decode(str);
+    }
+
+    /**
+     * Convert a String to a Long.
+     * 
+     * Returns null if the string is null.
+     *
+     * @param str  a String to convert, may be null
+     * @return converted Long
+     * @throws NumberFormatException if the value cannot be converted
+     */
+    public static Long createLong(String str) {
+        if (str == null) {
+            return null;
+        }
+        return Long.valueOf(str);
+    }
+
+    /**
+     * Convert a String to a BigInteger.
+     *
+     * Returns null if the string is null.
+     * 
+     * @param str  a String to convert, may be null
+     * @return converted BigInteger
+     * @throws NumberFormatException if the value cannot be converted
+     */
+    public static BigInteger createBigInteger(String str) {
+        if (str == null) {
+            return null;
+        }
+        return new BigInteger(str);
+    }
+
+    /**
+     * Convert a String to a BigDecimal.
+     * 
+     * Returns null if the string is null.
+     *
+     * @param str  a String to convert, may be null
+     * @return converted BigDecimal
+     * @throws NumberFormatException if the value cannot be converted
+     */
+    public static BigDecimal createBigDecimal(String str) {
+        if (str == null) {
+            return null;
+        }
+        // handle JDK1.3.1 bug where "" throws IndexOutOfBoundsException
+        if (StringUtils.isBlank(str)) {
+            throw new NumberFormatException("A blank string is not a valid number");
+        }  
+        return new BigDecimal(str);
+    }
+
+    // Min in array
+    //--------------------------------------------------------------------
+    /**
+     * Returns the minimum value in an array.
+     * 
+     * @param array  an array, must not be null or empty
+     * @return the minimum value in the array
+     * @throws IllegalArgumentException if array is null
+     * @throws IllegalArgumentException if array is empty
+     */
+    public static long min(long[] array) {
+        // Validates input
+        if (array == null) {
+            throw new IllegalArgumentException("The Array must not be null");
+        } else if (array.length == 0) {
+            throw new IllegalArgumentException("Array cannot be empty.");
+        }
+    
+        // Finds and returns min
+        long min = array[0];
+        for (int i = 1; i < array.length; i++) {
+            if (array[i] < min) {
+                min = array[i];
+            }
+        }
+    
+        return min;
+    }
+
+    /**
+     * Returns the minimum value in an array.
+     * 
+     * @param array  an array, must not be null or empty
+     * @return the minimum value in the array
+     * @throws IllegalArgumentException if array is null
+     * @throws IllegalArgumentException if array is empty
+     */
+    public static int min(int[] array) {
+        // Validates input
+        if (array == null) {
+            throw new IllegalArgumentException("The Array must not be null");
+        } else if (array.length == 0) {
+            throw new IllegalArgumentException("Array cannot be empty.");
+        }
+    
+        // Finds and returns min
+        int min = array[0];
+        for (int j = 1; j < array.length; j++) {
+            if (array[j] < min) {
+                min = array[j];
+            }
+        }
+    
+        return min;
+    }
+
+    /**
+     * Returns the minimum value in an array.
+     * 
+     * @param array  an array, must not be null or empty
+     * @return the minimum value in the array
+     * @throws IllegalArgumentException if array is null
+     * @throws IllegalArgumentException if array is empty
+     */
+    public static short min(short[] array) {
+        // Validates input
+        if (array == null) {
+            throw new IllegalArgumentException("The Array must not be null");
+        } else if (array.length == 0) {
+            throw new IllegalArgumentException("Array cannot be empty.");
+        }
+    
+        // Finds and returns min
+        short min = array[0];
+        for (int i = 1; i < array.length; i++) {
+            if (array[i] < min) {
+                min = array[i];
+            }
+        }
+    
+        return min;
+    }
+
+     /**
+     * Returns the minimum value in an array.
+     * 
+     * @param array  an array, must not be null or empty
+     * @return the minimum value in the array
+     * @throws IllegalArgumentException if array is null
+     * @throws IllegalArgumentException if array is empty
+     */
+    public static double min(double[] array) {
+        // Validates input
+        if (array == null) {
+            throw new IllegalArgumentException("The Array must not be null");
+        } else if (array.length == 0) {
+            throw new IllegalArgumentException("Array cannot be empty.");
+        }
+    
+        // Finds and returns min
+        double min = array[0];
+        for (int i = 1; i < array.length; i++) {
+            if (array[i] < min) {
+                min = array[i];
+            }
+        }
+    
+        return min;
+    }
+
+    /**
+     * Returns the minimum value in an array.
+     * 
+     * @param array  an array, must not be null or empty
+     * @return the minimum value in the array
+     * @throws IllegalArgumentException if array is null
+     * @throws IllegalArgumentException if array is empty
+     */
+    public static float min(float[] array) {
+        // Validates input
+        if (array == null) {
+            throw new IllegalArgumentException("The Array must not be null");
+        } else if (array.length == 0) {
+            throw new IllegalArgumentException("Array cannot be empty.");
+        }
+    
+        // Finds and returns min
+        float min = array[0];
+        for (int i = 1; i < array.length; i++) {
+            if (array[i] < min) {
+                min = array[i];
+            }
+        }
+    
+        return min;
+    }
+
+    // Max in array
+    //--------------------------------------------------------------------
+    /**
+     * Returns the maximum value in an array.
+     * 
+     * @param array  an array, must not be null or empty
+     * @return the minimum value in the array
+     * @throws IllegalArgumentException if array is null
+     * @throws IllegalArgumentException if array is empty
+     */
+    public static long max(long[] array) {
+        // Validates input
+        if (array == null) {
+            throw new IllegalArgumentException("The Array must not be null");
+        } else if (array.length == 0) {
+            throw new IllegalArgumentException("Array cannot be empty.");
+        }
+
+        // Finds and returns max
+        long max = array[0];
+        for (int j = 1; j < array.length; j++) {
+            if (array[j] > max) {
+                max = array[j];
+            }
+        }
+
+        return max;
+    }
+
+    /**
+     * Returns the maximum value in an array.
+     * 
+     * @param array  an array, must not be null or empty
+     * @return the minimum value in the array
+     * @throws IllegalArgumentException if array is null
+     * @throws IllegalArgumentException if array is empty
+     */
+    public static int max(int[] array) {
+        // Validates input
+        if (array == null) {
+            throw new IllegalArgumentException("The Array must not be null");
+        } else if (array.length == 0) {
+            throw new IllegalArgumentException("Array cannot be empty.");
+        }
+    
+        // Finds and returns max
+        int max = array[0];
+        for (int j = 1; j < array.length; j++) {
+            if (array[j] > max) {
+                max = array[j];
+            }
+        }
+    
+        return max;
+    }
+
+    /**
+     * Returns the maximum value in an array.
+     * 
+     * @param array  an array, must not be null or empty
+     * @return the minimum value in the array
+     * @throws IllegalArgumentException if array is null
+     * @throws IllegalArgumentException if array is empty
+     */
+    public static short max(short[] array) {
+        // Validates input
+        if (array == null) {
+            throw new IllegalArgumentException("The Array must not be null");
+        } else if (array.length == 0) {
+            throw new IllegalArgumentException("Array cannot be empty.");
+        }
+    
+        // Finds and returns max
+        short max = array[0];
+        for (int i = 1; i < array.length; i++) {
+            if (array[i] > max) {
+                max = array[i];
+            }
+        }
+    
+        return max;
+    }
+
+    /**
+     * Returns the maximum value in an array.
+     * 
+     * @param array  an array, must not be null or empty
+     * @return the minimum value in the array
+     * @throws IllegalArgumentException if array is null
+     * @throws IllegalArgumentException if array is empty
+     */
+    public static double max(double[] array) {
+        // Validates input
+        if (array== null) {
+            throw new IllegalArgumentException("The Array must not be null");
+        } else if (array.length == 0) {
+            throw new IllegalArgumentException("Array cannot be empty.");
+        }
+    
+        // Finds and returns max
+        double max = array[0];
+        for (int j = 1; j < array.length; j++) {
+            if (array[j] > max) {
+                max = array[j];
+            }
+        }
+    
+        return max;
+    }
+
+    /**
+     * Returns the maximum value in an array.
+     * 
+     * @param array  an array, must not be null or empty
+     * @return the minimum value in the array
+     * @throws IllegalArgumentException if array is null
+     * @throws IllegalArgumentException if array is empty
+     */
+    public static float max(float[] array) {
+        // Validates input
+        if (array == null) {
+            throw new IllegalArgumentException("The Array must not be null");
+        } else if (array.length == 0) {
+            throw new IllegalArgumentException("Array cannot be empty.");
+        }
+
+        // Finds and returns max
+        float max = array[0];
+        for (int j = 1; j < array.length; j++) {
+            if (array[j] > max) {
+                max = array[j];
+            }
+        }
+
+        return max;
+    }
+     
+    // 3 param min
+    //-----------------------------------------------------------------------
+    /**
+     * Gets the minimum of three long values.
+     * 
+     * @param a  value 1
+     * @param b  value 2
+     * @param c  value 3
+     * @return  the smallest of the values
+     */
+    public static long min(long a, long b, long c) {
+        if (b < a) {
+            a = b;
+        }
+        if (c < a) {
+            a = c;
+        }
+        return a;
+    }
+
+    /**
+     * Gets the minimum of three int values.
+     * 
+     * @param a  value 1
+     * @param b  value 2
+     * @param c  value 3
+     * @return  the smallest of the values
+     */
+    public static int min(int a, int b, int c) {
+        if (b < a) {
+            a = b;
+        }
+        if (c < a) {
+            a = c;
+        }
+        return a;
+    }
+
+    /**
+     * Gets the minimum of three short values.
+     * 
+     * @param a  value 1
+     * @param b  value 2
+     * @param c  value 3
+     * @return  the smallest of the values
+     */
+    public static short min(short a, short b, short c) {
+        if (b < a) {
+            a = b;
+        }
+        if (c < a) {
+            a = c;
+        }
+        return a;
+    }
+
+    /**
+     * Gets the minimum of three byte values.
+     * 
+     * @param a  value 1
+     * @param b  value 2
+     * @param c  value 3
+     * @return  the smallest of the values
+     */
+    public static byte min(byte a, byte b, byte c) {
+        if (b < a) {
+            a = b;
+        }
+        if (c < a) {
+            a = c;
+        }
+        return a;
+    }
+
+    /**
+     * Gets the minimum of three double values.
+     * 
+     * If any value is NaN, NaN is
+     * returned. Infinity is handled.
+     * 
+     * @param a  value 1
+     * @param b  value 2
+     * @param c  value 3
+     * @return  the smallest of the values
+     */
+    public static double min(double a, double b, double c) {
+        return Math.min(Math.min(a, b), c);
+    }
+
+    /**
+     * Gets the minimum of three float values.
+     * 
+     * If any value is NaN, NaN is
+     * returned. Infinity is handled.
+     *
+     * @param a  value 1
+     * @param b  value 2
+     * @param c  value 3
+     * @return  the smallest of the values
+     */
+    public static float min(float a, float b, float c) {
+        return Math.min(Math.min(a, b), c);
+    }
+
+    // 3 param max
+    //-----------------------------------------------------------------------
+    /**
+     * Gets the maximum of three long values.
+     * 
+     * @param a  value 1
+     * @param b  value 2
+     * @param c  value 3
+     * @return  the largest of the values
+     */
+    public static long max(long a, long b, long c) {
+        if (b > a) {
+            a = b;
+        }
+        if (c > a) {
+            a = c;
+        }
+        return a;
+    }
+
+    /**
+     * Gets the maximum of three int values.
+     * 
+     * @param a  value 1
+     * @param b  value 2
+     * @param c  value 3
+     * @return  the largest of the values
+     */
+    public static int max(int a, int b, int c) {
+        if (b > a) {
+            a = b;
+        }
+        if (c > a) {
+            a = c;
+        }
+        return a;
+    }
+
+    /**
+     * Gets the maximum of three short values.
+     * 
+     * @param a  value 1
+     * @param b  value 2
+     * @param c  value 3
+     * @return  the largest of the values
+     */
+    public static short max(short a, short b, short c) {
+        if (b > a) {
+            a = b;
+        }
+        if (c > a) {
+            a = c;
+        }
+        return a;
+    }
+
+    /**
+     * Gets the maximum of three byte values.
+     * 
+     * @param a  value 1
+     * @param b  value 2
+     * @param c  value 3
+     * @return  the largest of the values
+     */
+    public static byte max(byte a, byte b, byte c) {
+        if (b > a) {
+            a = b;
+        }
+        if (c > a) {
+            a = c;
+        }
+        return a;
+    }
+
+    /**
+     * Gets the maximum of three double values.
+     * 
+     * If any value is NaN, NaN is
+     * returned. Infinity is handled.
+     *
+     * @param a  value 1
+     * @param b  value 2
+     * @param c  value 3
+     * @return  the largest of the values
+     */
+    public static double max(double a, double b, double c) {
+        return Math.max(Math.max(a, b), c);
+    }
+
+    /**
+     * Gets the maximum of three float values.
+     * 
+     * If any value is NaN, NaN is
+     * returned. Infinity is handled.
+     *
+     * @param a  value 1
+     * @param b  value 2
+     * @param c  value 3
+     * @return  the largest of the values
+     */
+    public static float max(float a, float b, float c) {
+        return Math.max(Math.max(a, b), c);
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Compares two doubles for order.
+     *
+     * This method is more comprehensive than the standard Java greater
+     * than, less than and equals operators.
+     * 
+     *  - It returns 
-1 if the first value is less than the second. 
+     *  - It returns 
+1 if the first value is greater than the second. 
+     *  - It returns 
0 if the values are equal. 
+     * 
+     *
+     * 
+     * The ordering is as follows, largest to smallest:
+     * 
+     *  - NaN
+     *  
 - Positive infinity
+     *  
 - Maximum double
+     *  
 - Normal positve numbers
+     *  
 - +0.0
+     *  
 - -0.0
+     *  
 - Normal negative numbers
+     *  
 - Minimum double (
-Double.MAX_VALUE)
+     *   - Negative infinity
+     * 
 
+     * 
+     *
+     * Comparing NaN with NaN will
+     * return 0.
+     * 
+     * @param lhs  the first double
+     * @param rhs  the second double
+     * @return -1 if lhs is less, +1 if greater,
+     *  0 if equal to rhs
+     */
+    public static int compare(double lhs, double rhs) {
+        if (lhs < rhs) {
+            return -1;
+        }
+        if (lhs > rhs) {
+            return +1;
+        }
+        // Need to compare bits to handle 0.0 == -0.0 being true
+        // compare should put -0.0 < +0.0
+        // Two NaNs are also == for compare purposes
+        // where NaN == NaN is false
+        long lhsBits = Double.doubleToLongBits(lhs);
+        long rhsBits = Double.doubleToLongBits(rhs);
+        if (lhsBits == rhsBits) {
+            return 0;
+        }
+        // Something exotic! A comparison to NaN or 0.0 vs -0.0
+        // Fortunately NaN's long is > than everything else
+        // Also negzeros bits < poszero
+        // NAN: 9221120237041090560
+        // MAX: 9218868437227405311
+        // NEGZERO: -9223372036854775808
+        if (lhsBits < rhsBits) {
+            return -1;
+        } else {
+            return +1;
+        }
+    }
+    
+    /**
+     * Compares two floats for order.
+     *
+     * This method is more comprhensive than the standard Java greater than,
+     * less than and equals operators.
+     * 
+     *  - It returns 
-1 if the first value is less than the second.
+     *   - It returns 
+1 if the first value is greater than the second.
+     *   - It returns 
0 if the values are equal.
+     *  
+     *
+     *  The ordering is as follows, largest to smallest:
+     * 
+     * - NaN
+     * 
 - Positive infinity
+     * 
 - Maximum float
+     * 
 - Normal positve numbers
+     * 
 - +0.0
+     * 
 - -0.0
+     * 
 - Normal negative numbers
+     * 
 - Minimum float (
-Float.MAX_VALUE)
+     *  - Negative infinity
+     * 
 
+     *
+     * Comparing NaN with NaN will return
+     * 0.
+     * 
+     * @param lhs  the first float
+     * @param rhs  the second float
+     * @return -1 if lhs is less, +1 if greater,
+     *  0 if equal to rhs
+     */
+    public static int compare(float lhs, float rhs) {
+        if (lhs < rhs) {
+            return -1;
+        }
+        if (lhs > rhs) {
+            return +1;
+        }
+        //Need to compare bits to handle 0.0 == -0.0 being true
+        // compare should put -0.0 < +0.0
+        // Two NaNs are also == for compare purposes
+        // where NaN == NaN is false
+        int lhsBits = Float.floatToIntBits(lhs);
+        int rhsBits = Float.floatToIntBits(rhs);
+        if (lhsBits == rhsBits) {
+            return 0;
+        }
+        //Something exotic! A comparison to NaN or 0.0 vs -0.0
+        //Fortunately NaN's int is > than everything else
+        //Also negzeros bits < poszero
+        //NAN: 2143289344
+        //MAX: 2139095039
+        //NEGZERO: -2147483648
+        if (lhsBits < rhsBits) {
+            return -1;
+        } else {
+            return +1;
+        }
+    }
+    
+    //-----------------------------------------------------------------------
+    /**
+     * Checks whether the String contains only
+     * digit characters.
+     *
+     * Null and empty String will return
+     * false.
+     *
+     * @param str  the String to check
+     * @return true if str contains only unicode numeric
+     */
+    public static boolean isDigits(String str) {
+        if ((str == null) || (str.length() == 0)) {
+            return false;
+        }
+        for (int i = 0; i < str.length(); i++) {
+            if (!Character.isDigit(str.charAt(i))) {
+                return false;
+            }
+        }
+        return true;
+    }
+
+    /**
+     * Checks whether the String a valid Java number.
+     *
+     * Valid numbers include hexadecimal marked with the 0x
+     * qualifier, scientific notation and numbers marked with a type
+     * qualifier (e.g. 123L).
+     *
+     * Null and empty String will return
+     * false.
+     *
+     * @param str  the String to check
+     * @return true if the string is a correctly formatted number
+     */
+    public static boolean isNumber(String str) {
+        if ((str == null) || (str.length() == 0)) {
+            return false;
+        }
+        char[] chars = str.toCharArray();
+        int sz = chars.length;
+        boolean hasExp = false;
+        boolean hasDecPoint = false;
+        boolean allowSigns = false;
+        boolean foundDigit = false;
+        // deal with any possible sign up front
+        int start = (chars[0] == '-') ? 1 : 0;
+        if (sz > start + 1) {
+            if (chars[start] == '0' && chars[start + 1] == 'x') {
+                int i = start + 2;
+                if (i == sz) {
+                    return false; // str == "0x"
+                }
+                // checking hex (it can't be anything else)
+                for (; i < chars.length; i++) {
+                    if ((chars[i] < '0' || chars[i] > '9')
+                        && (chars[i] < 'a' || chars[i] > 'f')
+                        && (chars[i] < 'A' || chars[i] > 'F')) {
+                        return false;
+                    }
+                }
+                return true;
+            }
+        }
+        sz--; // don't want to loop to the last char, check it afterwords
+              // for type qualifiers
+        int i = start;
+        // loop to the next to last char or to the last char if we need another digit to
+        // make a valid number (e.g. chars[0..5] = "1234E")
+        while (i < sz || (i < sz + 1 && allowSigns && !foundDigit)) {
+            if (chars[i] >= '0' && chars[i] <= '9') {
+                foundDigit = true;
+                allowSigns = false;
+
+            } else if (chars[i] == '.') {
+                if (hasDecPoint || hasExp) {
+                    // two decimal points or dec in exponent   
+                    return false;
+                }
+                hasDecPoint = true;
+            } else if (chars[i] == 'e' || chars[i] == 'E') {
+                // we've already taken care of hex.
+                if (hasExp) {
+                    // two E's
+                    return false;
+                }
+                if (!foundDigit) {
+                    return false;
+                }
+                hasExp = true;
+                allowSigns = true;
+            } else if (chars[i] == '+' || chars[i] == '-') {
+                if (!allowSigns) {
+                    return false;
+                }
+                allowSigns = false;
+                foundDigit = false; // we need a digit after the E
+            } else {
+                return false;
+            }
+            i++;
+        }
+        if (i < chars.length) {
+            if (chars[i] >= '0' && chars[i] <= '9') {
+                // no type qualifier, OK
+                return true;
+            }
+            if (chars[i] == 'e' || chars[i] == 'E') {
+                // can't have an E at the last byte
+                return false;
+            }
+            if (!allowSigns
+                && (chars[i] == 'd'
+                    || chars[i] == 'D'
+                    || chars[i] == 'f'
+                    || chars[i] == 'F')) {
+                return foundDigit;
+            }
+            if (chars[i] == 'l'
+                || chars[i] == 'L') {
+                // not allowing L with an exponoent
+                return foundDigit && !hasExp;
+            }
+            // last character is illegal
+            return false;
+        }
+        // allowSigns is true iff the val ends in 'E'
+        // found digit it to make sure weird stuff like '.' and '1E-' doesn't pass
+        return !allowSigns && foundDigit;
+    }
+    
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/math/RandomUtils.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/math/RandomUtils.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/math/RandomUtils.java	30 Aug 2012 16:24:43 -0000	1.1
@@ -0,0 +1,153 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang.math;
+
+import java.util.Random;
+
+/**
+ * RandomUtils is a wrapper that supports all possible 
+ * {@link java.util.Random} methods via the {@link java.lang.Math#random()}
+ * method and its system-wide Random object.
+ * 
+ * @author Henri Yandell
+ * @since 2.0
+ * @version $Id: RandomUtils.java,v 1.1 2012/08/30 16:24:43 marcin Exp $
+ */
+public class RandomUtils {
+
+    public static final Random JVM_RANDOM = new JVMRandom();
+
+// should be possible for JVM_RANDOM?
+//    public static void nextBytes(byte[]) {
+//    public synchronized double nextGaussian();
+//    }
+
+    /**
+     * 
Returns the next pseudorandom, uniformly distributed int value
+     * from the Math.random() sequence.
+     *
+     * @return the random int
+     */
+    public static int nextInt() {
+        return nextInt(JVM_RANDOM);
+    }
+    public static int nextInt(Random rnd) {
+        return rnd.nextInt();
+    }
+    /**
+     * Returns a pseudorandom, uniformly distributed int value
+     * between 0 (inclusive) and the specified value
+     * (exclusive), from the Math.random() sequence.
+     *
+     * @param n  the specified exclusive max-value
+     *
+     * @return the random int
+     */
+    public static int nextInt(int n) {
+        return nextInt(JVM_RANDOM, n);
+    }
+    public static int nextInt(Random rnd, int n) {
+        // check this cannot return 'n'
+        return rnd.nextInt(n);
+    }
+    /**
+     * Returns the next pseudorandom, uniformly distributed long value
+     * from the Math.random() sequence.
+     *
+     * @return the random long
+     */
+    public static long nextLong() {
+        return nextLong(JVM_RANDOM);
+    }
+    public static long nextLong(Random rnd) {
+        return rnd.nextLong();
+    }
+    /**
+     * Returns the next pseudorandom, uniformly distributed boolean value
+     * from the Math.random() sequence.
+     *
+     * @return the random boolean
+     */
+    public static boolean nextBoolean() {
+        return nextBoolean(JVM_RANDOM);
+    }
+    public static boolean nextBoolean(Random rnd) {
+        return rnd.nextBoolean();
+    }
+    /**
+     * Returns the next pseudorandom, uniformly distributed float value
+     * between 0.0 and 1.0 from the Math.random()
+     * sequence.
+     *
+     * @return the random float
+     */
+    public static float nextFloat() {
+        return nextFloat(JVM_RANDOM);
+    }
+    public static float nextFloat(Random rnd) {
+        return rnd.nextFloat();
+    }
+    /**
+     * Synonymous to the Math.random() call.
+     *
+     * @return the random double
+     */
+    public static double nextDouble() {
+        return nextDouble(JVM_RANDOM);
+    }
+    public static double nextDouble(Random rnd) {
+        return rnd.nextDouble();
+    }
+    
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/math/Range.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/math/Range.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/math/Range.java	30 Aug 2012 16:24:43 -0000	1.1
@@ -0,0 +1,468 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang.math;
+
+/**
+ * Range represents a range of numbers of the same type.
+ * 
+ * Specific subclasses hold the range values as different types. Each
+ * subclass should be immutable and {@link java.io.Serializable Serializable}
+ * if possible.
+ *
+ * @author Stephen Colebourne
+ * @since 2.0
+ * @version $Id: Range.java,v 1.1 2012/08/30 16:24:43 marcin Exp $
+ */
+public abstract class Range {
+
+    /**
+     * Constructs a new range.
+     */
+    public Range() {
+        super();
+    }
+
+    // Accessors
+    //--------------------------------------------------------------------
+
+    /**
+     * Gets the minimum number in this range.
+     *
+     * @return the minimum number in this range
+     */
+    public abstract Number getMinimumNumber();
+
+    /**
+     * Gets the minimum number in this range as a long.
+     * 
+     * This implementation uses the {@link #getMinimumNumber()} method. 
+     * Subclasses may be able to optimise this.
+     *
+     * @return the minimum number in this range
+     */
+    public long getMinimumLong() {
+        return getMinimumNumber().longValue();
+    }
+
+    /**
+     * Gets the minimum number in this range as a int.
+     * 
+     * This implementation uses the {@link #getMinimumNumber()} method. 
+     * Subclasses may be able to optimise this.
+     *
+     * @return the minimum number in this range
+     */
+    public int getMinimumInteger() {
+        return getMinimumNumber().intValue();
+    }
+
+    /**
+     * Gets the minimum number in this range as a double.
+     * 
+     * This implementation uses the {@link #getMinimumNumber()} method. 
+     * Subclasses may be able to optimise this.
+     *
+     * @return the minimum number in this range
+     */
+    public double getMinimumDouble() {
+        return getMinimumNumber().doubleValue();
+    }
+
+    /**
+     * Gets the minimum number in this range as a float.
+     * 
+     * This implementation uses the {@link #getMinimumNumber()} method. 
+     * Subclasses may be able to optimise this.
+     *
+     * @return the minimum number in this range
+     */
+    public float getMinimumFloat() {
+        return getMinimumNumber().floatValue();
+    }
+
+    /**
+     * Gets the maximum number in this range.
+     *
+     * @return the maximum number in this range
+     */
+    public abstract Number getMaximumNumber();
+
+    /**
+     * Gets the maximum number in this range as a long.
+     * 
+     * This implementation uses the {@link #getMaximumNumber()} method. 
+     * Subclasses may be able to optimise this.
+     *
+     * @return the maximum number in this range
+     */
+    public long getMaximumLong() {
+        return getMaximumNumber().longValue();
+    }
+
+    /**
+     * Gets the maximum number in this range as a int.
+     * 
+     * This implementation uses the {@link #getMaximumNumber()} method. 
+     * Subclasses may be able to optimise this.
+     *
+     * @return the maximum number in this range
+     */
+    public int getMaximumInteger() {
+        return getMaximumNumber().intValue();
+    }
+
+    /**
+     * Gets the maximum number in this range as a double.
+     * 
+     * This implementation uses the {@link #getMaximumNumber()} method. 
+     * Subclasses may be able to optimise this.
+     *
+     * @return the maximum number in this range
+     */
+    public double getMaximumDouble() {
+        return getMaximumNumber().doubleValue();
+    }
+
+    /**
+     * Gets the maximum number in this range as a float.
+     * 
+     * This implementation uses the {@link #getMaximumNumber()} method. 
+     * Subclasses may be able to optimise this.
+     *
+     * @return the maximum number in this range
+     */
+    public float getMaximumFloat() {
+        return getMaximumNumber().floatValue();
+    }
+
+    // Include tests
+    //--------------------------------------------------------------------
+    
+    /**
+     * Tests whether the specified Number occurs within
+     * this range.
+     * 
+     * The exact comparison implementation varies by subclass. It is
+     * intended that an int specific subclass will compare using
+     * int comparison.
+     * 
+     * null is handled and returns false.
+     *
+     * @param number  the number to test, may be null
+     * @return true if the specified number occurs within this range
+     * @throws IllegalArgumentException if the Number cannot be compared
+     */
+    public abstract boolean containsNumber(Number number);
+
+    /**
+     * Tests whether the specified Number occurs within
+     * this range using long comparison..
+     * 
+     * null is handled and returns false.
+     * 
+     * This implementation forwards to the {@link #containsLong(long)} method.
+     *
+     * @param value  the long to test, may be null
+     * @return true if the specified number occurs within this
+     *  range by long comparison
+     */
+    public boolean containsLong(Number value) {
+        if (value == null) {
+            return false;
+        }
+        return containsLong(value.longValue());
+    }
+
+    /**
+     * Tests whether the specified long occurs within
+     * this range using long comparison.
+     * 
+     * This implementation uses the {@link #getMinimumLong()} and 
+     * {@link #getMaximumLong()} methods and should be good for most uses.
+     * 
+     * @param value  the long to test
+     * @return true if the specified number occurs within this
+     *  range by long comparison
+     */
+    public boolean containsLong(long value) {
+        return (value >= getMinimumLong() && value <= getMaximumLong());
+    }
+
+    /**
+     * Tests whether the specified Number occurs within
+     * this range using int comparison..
+     * 
+     * null is handled and returns false.
+     * 
+     * This implementation forwards to the {@link #containsInteger(int)} method.
+     *
+     * @param value  the integer to test, may be null
+     * @return true if the specified number occurs within this
+     *  range by int comparison
+     */
+    public boolean containsInteger(Number value) {
+        if (value == null) {
+            return false;
+        }
+        return containsInteger(value.intValue());
+    }
+
+    /**
+     * Tests whether the specified int occurs within
+     * this range using int comparison.
+     * 
+     * This implementation uses the {@link #getMinimumInteger()} and 
+     * {@link #getMaximumInteger()} methods and should be good for most uses.
+     * 
+     * @param value  the int to test
+     * @return true if the specified number occurs within this
+     *  range by int comparison
+     */
+    public boolean containsInteger(int value) {
+        return (value >= getMinimumInteger() && value <= getMaximumInteger());
+    }
+
+    /**
+     * Tests whether the specified Number occurs within
+     * this range using double comparison..
+     * 
+     * null is handled and returns false.
+     * 
+     * This implementation forwards to the {@link #containsDouble(double)} method.
+     *
+     * @param value  the double to test, may be null
+     * @return true if the specified number occurs within this
+     *  range by double comparison
+     */
+    public boolean containsDouble(Number value) {
+        if (value == null) {
+            return false;
+        }
+        return containsDouble(value.doubleValue());
+    }
+
+    /**
+     * Tests whether the specified double occurs within
+     * this range using double comparison.
+     * 
+     * This implementation uses the {@link #getMinimumDouble()} and 
+     * {@link #getMaximumDouble()} methods and should be good for most uses.
+     * 
+     * @param value  the double to test
+     * @return true if the specified number occurs within this
+     *  range by double comparison
+     */
+    public boolean containsDouble(double value) {
+        int compareMin = NumberUtils.compare(getMinimumDouble(), value);
+        int compareMax = NumberUtils.compare(getMaximumDouble(), value);
+        return (compareMin <= 0 && compareMax >= 0);
+    }
+
+    /**
+     * Tests whether the specified Number occurs within
+     * this range using float comparison.
+     * 
+     * null is handled and returns false.
+     * 
+     * This implementation forwards to the {@link #containsFloat(float)} method.
+     *
+     * @param value  the float to test, may be null
+     * @return true if the specified number occurs within this
+     *  range by float comparison
+     */
+    public boolean containsFloat(Number value) {
+        if (value == null) {
+            return false;
+        }
+        return containsFloat(value.floatValue());
+    }
+
+    /**
+     * Tests whether the specified float occurs within
+     * this range using float comparison.
+     * 
+     * This implementation uses the {@link #getMinimumFloat()} and 
+     * {@link #getMaximumFloat()} methods and should be good for most uses.
+     * 
+     * @param value  the float to test
+     * @return true if the specified number occurs within this
+     *  range by float comparison
+     */
+    public boolean containsFloat(float value) {
+        int compareMin = NumberUtils.compare(getMinimumFloat(), value);
+        int compareMax = NumberUtils.compare(getMaximumFloat(), value);
+        return (compareMin <= 0 && compareMax >= 0);
+    }
+
+    // Range tests
+    //--------------------------------------------------------------------
+
+    /**
+     * Tests whether the specified range occurs entirely within this range.
+     * 
+     * The exact comparison implementation varies by subclass. It is
+     * intended that an int specific subclass will compare using
+     * int comparison.
+     * 
+     * null is handled and returns false.
+     * 
+     * This implementation uses the {@link #containsNumber(Number)} method.
+     * Subclasses may be able to optimise this.
+     *
+     * @param range  the range to test, may be null
+     * @return true if the specified range occurs entirely within
+     *  this range; otherwise, false
+     * @throws IllegalArgumentException if the Range cannot be compared
+     */
+    public boolean containsRange(Range range) {
+        if (range == null) {
+            return false;
+        }
+        return containsNumber(range.getMinimumNumber()) 
+            && containsNumber(range.getMaximumNumber());
+    }
+
+    /**
+     * Tests whether the specified range overlaps with this range.
+     * 
+     * The exact comparison implementation varies by subclass. It is
+     * intended that an int specific subclass will compare using
+     * int comparison.
+     * 
+     * null is handled and returns false.
+     * 
+     * This implementation uses the {@link #containsNumber(Number)} and
+     * {@link #containsRange(Range)} methods.
+     * Subclasses may be able to optimise this.
+     *
+     * @param range  the range to test, may be null
+     * @return true if the specified range overlaps with this
+     *  range; otherwise, false
+     * @throws IllegalArgumentException if the Range cannot be compared
+     */
+    public boolean overlapsRange(Range range) {
+        if (range == null) {
+            return false;
+        }
+        return range.containsNumber(getMinimumNumber())
+            || range.containsNumber(getMaximumNumber())
+            || containsNumber(range.getMinimumNumber());
+    }
+
+    // Basics
+    //--------------------------------------------------------------------
+
+    /**
+     * Compares this range to another object to test if they are equal.
.
+     * 
+     * To be equal, the class, minimum and maximum must be equal.
+     * 
+     * This implementation uses the {@link #getMinimumNumber()} and 
+     * {@link #getMaximumNumber()} methods. 
+     * Subclasses may be able to optimise this.
+     *
+     * @param obj the reference object with which to compare
+     * @return true if this object is equal
+     */
+    public boolean equals(Object obj) {
+        if (obj == this) {
+            return true;
+        } else if (obj == null || obj.getClass() != getClass()) {
+            return false;
+        } else {
+            Range range = (Range) obj;
+            return getMinimumNumber().equals(range.getMinimumNumber()) &&
+                   getMaximumNumber().equals(range.getMaximumNumber());
+        }
+    }
+
+    /**
+     * Gets a hashCode for the range.
+     * 
+     * This implementation uses the {@link #getMinimumNumber()} and 
+     * {@link #getMaximumNumber()} methods. 
+     * Subclasses may be able to optimise this.
+     *
+     * @return a hash code value for this object
+     */
+    public int hashCode() {
+        int result = 17;
+        result = 37 * result + getClass().hashCode();
+        result = 37 * result + getMinimumNumber().hashCode();
+        result = 37 * result + getMaximumNumber().hashCode();
+        return result;
+    }
+
+    /**
+     * Gets the range as a String.
+     *
+     * The format of the String is 'Range[min,max]'.
+     * 
+     * This implementation uses the {@link #getMinimumNumber()} and 
+     * {@link #getMaximumNumber()} methods. 
+     * Subclasses may be able to optimise this.
+     *
+     * @return the String representation of this range
+     */
+    public String toString() {
+        StringBuffer buf = new StringBuffer(32);
+        buf.append("Range[");
+        buf.append(getMinimumNumber());
+        buf.append(',');
+        buf.append(getMaximumNumber());
+        buf.append(']');
+        return buf.toString();
+    }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/math/package.html
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/math/package.html,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/math/package.html	30 Aug 2012 16:24:43 -0000	1.1
@@ -0,0 +1,7 @@
+
+
+Extends java.math for business mathematical classes. This package is intended for business
+mathematical classes, not scientific ones.
+@since 2.0
+
+
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/time/DateFormatUtils.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/time/DateFormatUtils.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/time/DateFormatUtils.java	30 Aug 2012 16:24:43 -0000	1.1
@@ -0,0 +1,298 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang.time;
+
+import java.util.Date;
+import java.util.Locale;
+import java.util.TimeZone;
+
+/**
+ * Date and time formatting utilites and constants.
+ *
+ * Formatting is performed using the
+ * {@link org.apache.commons.lang.time.FastDateFormat} class.
+ *
+ * @author Apache Ant - DateUtils
+ * @author Stephane Bailliez
+ * @author Stefan Bodewig
+ * @author Stephen Colebourne
+ * @author Gary Gregory
+ * @since 2.0
+ * @version $Id: DateFormatUtils.java,v 1.1 2012/08/30 16:24:43 marcin Exp $
+ */
+public class DateFormatUtils {
+
+    /**
+     * ISO8601 formatter for date-time witout time zone.
+     * The format used is yyyy-MM-dd'T'HH:mm:ss.
+     */
+    public static final FastDateFormat ISO_DATETIME_FORMAT
+            = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ss");
+
+    /**
+     * ISO8601 formatter for date-time with time zone.
+     * The format used is yyyy-MM-dd'T'HH:mm:ssZZ.
+     */
+    public static final FastDateFormat ISO_DATETIME_TIME_ZONE_FORMAT
+            = FastDateFormat.getInstance("yyyy-MM-dd'T'HH:mm:ssZZ");
+
+    /**
+     * ISO8601 formatter for date without time zone.
+     * The format used is yyyy-MM-dd.
+     */
+    public static final FastDateFormat ISO_DATE_FORMAT
+            = FastDateFormat.getInstance("yyyy-MM-dd");
+
+    /**
+     * ISO8601-like formatter for date with time zone.
+     * The format used is yyyy-MM-ddZZ.
+     * This pattern does not comply with the formal ISO8601 specification
+     * as the standard does not allow a time zone  without a time.
+     */
+    public static final FastDateFormat ISO_DATE_TIME_ZONE_FORMAT
+            = FastDateFormat.getInstance("yyyy-MM-ddZZ");
+
+    /**
+     * ISO8601 formatter for time without time zone.
+     * The format used is 'T'HH:mm:ss.
+     */
+    public static final FastDateFormat ISO_TIME_FORMAT
+            = FastDateFormat.getInstance("'T'HH:mm:ss");
+
+    /**
+     * ISO8601 formatter for time with time zone.
+     * The format used is 'T'HH:mm:ssZZ.
+     */
+    public static final FastDateFormat ISO_TIME_TIME_ZONE_FORMAT
+            = FastDateFormat.getInstance("'T'HH:mm:ssZZ");
+
+    /**
+     * ISO8601-like formatter for time without time zone.
+     * The format used is HH:mm:ss.
+     * This pattern does not comply with the formal ISO8601 specification
+     * as the standard requires the 'T' prefix for times.
+     */
+    public static final FastDateFormat ISO_TIME_NO_T_FORMAT
+            = FastDateFormat.getInstance("HH:mm:ss");
+
+    /**
+     * ISO8601-like formatter for time with time zone.
+     * The format used is HH:mm:ssZZ.
+     * This pattern does not comply with the formal ISO8601 specification
+     * as the standard requires the 'T' prefix for times.
+     */
+    public static final FastDateFormat ISO_TIME_NO_T_TIME_ZONE_FORMAT
+            = FastDateFormat.getInstance("HH:mm:ssZZ");
+
+    /**
+     * SMTP (and probably other) date headers.
+     * The format used is EEE, dd MMM yyyy HH:mm:ss Z in US locale.
+     */
+    public static final FastDateFormat SMTP_DATETIME_FORMAT
+            = FastDateFormat.getInstance("EEE, dd MMM yyyy HH:mm:ss Z", Locale.US);
+
+    //-----------------------------------------------------------------------
+    /**
+     * DateFormatUtils instances should NOT be constructed in standard programming.
+     *
+     * This constructor is public to permit tools that require a JavaBean instance
+     * to operate.
+     */
+    public DateFormatUtils() {
+    }
+
+    /**
+     * Format a date/time into a specific pattern using the UTC time zone.
+     * 
+     * @param millis  the date to format expressed in milliseconds
+     * @param pattern  the pattern to use to format the date
+     * @return the formatted date
+     */
+    public static String formatUTC(long millis, String pattern) {
+        return format(new Date(millis), pattern, DateUtils.UTC_TIME_ZONE, null);
+    }
+
+    /**
+     * Format a date/time into a specific pattern using the UTC time zone.
+     * 
+     * @param date  the date to format
+     * @param pattern  the pattern to use to format the date
+     * @return the formatted date
+     */
+    public static String formatUTC(Date date, String pattern) {
+        return format(date, pattern, DateUtils.UTC_TIME_ZONE, null);
+    }
+    
+    /**
+     * Format a date/time into a specific pattern using the UTC time zone.
+     * 
+     * @param millis  the date to format expressed in milliseconds
+     * @param pattern  the pattern to use to format the date
+     * @param locale  the locale to use, may be null
+     * @return the formatted date
+     */
+    public static String formatUTC(long millis, String pattern, Locale locale) {
+        return format(new Date(millis), pattern, DateUtils.UTC_TIME_ZONE, locale);
+    }
+
+    /**
+     * Format a date/time into a specific pattern using the UTC time zone.
+     * 
+     * @param date  the date to format
+     * @param pattern  the pattern to use to format the date
+     * @param locale  the locale to use, may be null
+     * @return the formatted date
+     */
+    public static String formatUTC(Date date, String pattern, Locale locale) {
+        return format(date, pattern, DateUtils.UTC_TIME_ZONE, locale);
+    }
+    
+    /**
+     * Format a date/time into a specific pattern.
+     * 
+     * @param millis  the date to format expressed in milliseconds
+     * @param pattern  the pattern to use to format the date
+     * @return the formatted date
+     */
+    public static String format(long millis, String pattern) {
+        return format(new Date(millis), pattern, null, null);
+    }
+
+    /**
+     * Format a date/time into a specific pattern.
+     * 
+     * @param date  the date to format
+     * @param pattern  the pattern to use to format the date
+     * @return the formatted date
+     */
+    public static String format(Date date, String pattern) {
+        return format(date, pattern, null, null);
+    }
+    
+    /**
+     * Format a date/time into a specific pattern in a time zone.
+     * 
+     * @param millis  the time expressed in milliseconds
+     * @param pattern  the pattern to use to format the date
+     * @param timeZone  the time zone  to use, may be null
+     * @return the formatted date
+     */
+    public static String format(long millis, String pattern, TimeZone timeZone) {
+        return format(new Date(millis), pattern, timeZone, null);
+    }
+
+    /**
+     * Format a date/time into a specific pattern in a time zone.
+     * 
+     * @param date  the date to format
+     * @param pattern  the pattern to use to format the date
+     * @param timeZone  the time zone  to use, may be null
+     * @return the formatted date
+     */
+    public static String format(Date date, String pattern, TimeZone timeZone) {
+        return format(date, pattern, timeZone, null);
+    }
+
+    /**
+     * Format a date/time into a specific pattern in a locale.
+     * 
+     * @param millis  the date to format expressed in milliseconds
+     * @param pattern  the pattern to use to format the date
+     * @param locale  the locale to use, may be null
+     * @return the formatted date
+     */
+    public static String format(long millis, String pattern, Locale locale) {
+        return format(new Date(millis), pattern, null, locale);
+    }
+
+    /**
+     * Format a date/time into a specific pattern in a locale.
+     * 
+     * @param date  the date to format
+     * @param pattern  the pattern to use to format the date
+     * @param locale  the locale to use, may be null
+     * @return the formatted date
+     */
+    public static String format(Date date, String pattern, Locale locale) {
+        return format(date, pattern, null, locale);
+    }
+
+    /**
+     * Format a date/time into a specific pattern in a time zone  and locale.
+     * 
+     * @param millis  the date to format expressed in milliseconds
+     * @param pattern  the pattern to use to format the date
+     * @param timeZone  the time zone  to use, may be null
+     * @param locale  the locale to use, may be null
+     * @return the formatted date
+     */
+    public static String format(long millis, String pattern, TimeZone timeZone, Locale locale) {
+        return format(new Date(millis), pattern, timeZone, locale);
+    }
+
+    /**
+     * Format a date/time into a specific pattern in a time zone  and locale.
+     * 
+     * @param date  the date to format
+     * @param pattern  the pattern to use to format the date
+     * @param timeZone  the time zone  to use, may be null
+     * @param locale  the locale to use, may be null
+     * @return the formatted date
+     */
+    public static String format(Date date, String pattern, TimeZone timeZone, Locale locale) {
+        FastDateFormat df = FastDateFormat.getInstance(pattern, timeZone, locale);
+        return df.format(date);
+    }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/time/DateUtils.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/time/DateUtils.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/time/DateUtils.java	30 Aug 2012 16:24:43 -0000	1.1
@@ -0,0 +1,704 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang.time;
+
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+import java.util.TimeZone;
+
+/**
+ * A suite of utilities surrounding the use of the
+ * {@link java.util.Calendar} and {@link java.util.Date} object.
+ *
+ * @author Serge Knystautas
+ * @author Stephen Colebourne
+ * @author Janek Bogucki
+ * @author Gary Gregory
+ * @since 2.0
+ * @version $Id: DateUtils.java,v 1.1 2012/08/30 16:24:43 marcin Exp $
+ */
+public class DateUtils {
+    
+    /**
+     * The UTC time zone  (often referred to as GMT).
+     */
+    public static final TimeZone UTC_TIME_ZONE = TimeZone.getTimeZone("GMT");
+    /**
+     * Number of milliseconds in a standard second.
+     */
+    public static final int MILLIS_IN_SECOND = 1000;
+    /**
+     * Number of milliseconds in a standard minute.
+     */
+    public static final int MILLIS_IN_MINUTE = 60 * 1000;
+    /**
+     * Number of milliseconds in a standard hour.
+     */
+    public static final int MILLIS_IN_HOUR = 60 * 60 * 1000;
+    /**
+     * Number of milliseconds in a standard day.
+     */
+    public static final int MILLIS_IN_DAY = 24 * 60 * 60 * 1000;
+
+    /**
+     * This is half a month, so this represents whether a date is in the top
+     * or bottom half of the month.
+     */
+    public final static int SEMI_MONTH = 1001;
+
+    private static final int[][] fields = {
+            {Calendar.MILLISECOND},
+            {Calendar.SECOND},
+            {Calendar.MINUTE},
+            {Calendar.HOUR_OF_DAY, Calendar.HOUR},
+            {Calendar.DATE, Calendar.DAY_OF_MONTH, Calendar.AM_PM /* Calendar.DAY_OF_YEAR, Calendar.DAY_OF_WEEK, Calendar.DAY_OF_WEEK_IN_MONTH */},
+            {Calendar.MONTH, DateUtils.SEMI_MONTH},
+            {Calendar.YEAR},
+            {Calendar.ERA}};
+
+    /**
+     * A week range, starting on Sunday.
+     */
+    public final static int RANGE_WEEK_SUNDAY = 1;
+
+    /**
+     * A week range, starting on Monday.
+     */
+    public final static int RANGE_WEEK_MONDAY = 2;
+
+    /**
+     * A week range, starting on the day focused.
+     */
+    public final static int RANGE_WEEK_RELATIVE = 3;
+
+    /**
+     * A week range, centered around the day focused.
+     */
+    public final static int RANGE_WEEK_CENTER = 4;
+
+    /**
+     * A month range, the week starting on Sunday.
+     */
+    public final static int RANGE_MONTH_SUNDAY = 5;
+
+    /**
+     * A month range, the week starting on Monday.
+     */
+    public final static int RANGE_MONTH_MONDAY = 6;
+
+    /**
+     * DateUtils instances should NOT be constructed in
+     * standard programming. Instead, the class should be used as
+     * DateUtils.parse(str);.
+     *
+     * This constructor is public to permit tools that require a JavaBean
+     * instance to operate.
+     */
+    public DateUtils() {
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Round this date, leaving the field specified as the most
+     * significant field.
+     *
+     * For example, if you had the datetime of 28 Mar 2002
+     * 13:45:01.231, if this was passed with HOUR, it would return
+     * 28 Mar 2002 14:00:00.000. If this was passed with MONTH, it
+     * would return 1 April 2002 0:00:00.000.
+     * 
+     * @param date  the date to work with
+     * @param field  the field from Calendar
+     *  or SEMI_MONTH
+     * @return the rounded date
+     * @throws IllegalArgumentException if the date is null
+     */
+    public static Date round(Date date, int field) {
+        if (date == null) {
+            throw new IllegalArgumentException("The date must not be null");
+        }
+        GregorianCalendar gval = new GregorianCalendar();
+        gval.setTime(date);
+        modify(gval, field, true);
+        return gval.getTime();
+    }
+
+    /**
+     * Round this date, leaving the field specified as the most
+     * significant field.
+     *
+     * For example, if you had the datetime of 28 Mar 2002
+     * 13:45:01.231, if this was passed with HOUR, it would return
+     * 28 Mar 2002 14:00:00.000. If this was passed with MONTH, it
+     * would return 1 April 2002 0:00:00.000.
+     * 
+     * @param date  the date to work with
+     * @param field  the field from Calendar
+     *  or SEMI_MONTH
+     * @return the rounded date (a different object)
+     * @throws IllegalArgumentException if the date is null
+     */
+    public static Calendar round(Calendar date, int field) {
+        if (date == null) {
+            throw new IllegalArgumentException("The date must not be null");
+        }
+        Calendar rounded = (Calendar) date.clone();
+        modify(rounded, field, true);
+        return rounded;
+    }
+
+    /**
+     * Round this date, leaving the field specified as the most
+     * significant field.
+     *
+     * For example, if you had the datetime of 28 Mar 2002
+     * 13:45:01.231, if this was passed with HOUR, it would return
+     * 28 Mar 2002 14:00:00.000. If this was passed with MONTH, it
+     * would return 1 April 2002 0:00:00.000.
+     * 
+     * @param date  the date to work with, either Date or Calendar
+     * @param field  the field from Calendar
+     *  or SEMI_MONTH
+     * @return the rounded date
+     * @throws IllegalArgumentException if the date is null
+     * @throws ClassCastException if the object type is not a Date
+     *  or Calendar
+     */
+    public static Date round(Object date, int field) {
+        if (date == null) {
+            throw new IllegalArgumentException("The date must not be null");
+        }
+        if (date instanceof Date) {
+            return round((Date) date, field);
+        } else if (date instanceof Calendar) {
+            return round((Calendar) date, field).getTime();
+        } else {
+            throw new ClassCastException("Could not round " + date);
+        }
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Truncate this date, leaving the field specified as the most
+     * significant field.
+     *
+     * For example, if you had the datetime of 28 Mar 2002
+     * 13:45:01.231, if you passed with HOUR, it would return 28 Mar
+     * 2002 13:00:00.000.  If this was passed with MONTH, it would
+     * return 1 Mar 2002 0:00:00.000.
+     * 
+     * @param date  the date to work with
+     * @param field  the field from Calendar
+     *  or SEMI_MONTH
+     * @return the rounded date
+     * @throws IllegalArgumentException if the date is null
+     */
+    public static Date truncate(Date date, int field) {
+        if (date == null) {
+            throw new IllegalArgumentException("The date must not be null");
+        }
+        GregorianCalendar gval = new GregorianCalendar();
+        gval.setTime(date);
+        modify(gval, field, false);
+        return gval.getTime();
+    }
+
+    /**
+     * Truncate this date, leaving the field specified as the most
+     * significant field.
+     *
+     * For example, if you had the datetime of 28 Mar 2002
+     * 13:45:01.231, if you passed with HOUR, it would return 28 Mar
+     * 2002 13:00:00.000.  If this was passed with MONTH, it would
+     * return 1 Mar 2002 0:00:00.000.
+     * 
+     * @param date  the date to work with
+     * @param field  the field from Calendar
+     *  or SEMI_MONTH
+     * @return the rounded date (a different object)
+     * @throws IllegalArgumentException if the date is null
+     */
+    public static Calendar truncate(Calendar date, int field) {
+        if (date == null) {
+            throw new IllegalArgumentException("The date must not be null");
+        }
+        Calendar truncated = (Calendar) date.clone();
+        modify(truncated, field, false);
+        return truncated;
+    }
+
+    /**
+     * Truncate this date, leaving the field specified as the most
+     * significant field.
+     *
+     * For example, if you had the datetime of 28 Mar 2002
+     * 13:45:01.231, if you passed with HOUR, it would return 28 Mar
+     * 2002 13:00:00.000.  If this was passed with MONTH, it would
+     * return 1 Mar 2002 0:00:00.000.
+     * 
+     * @param date  the date to work with, either Date
+     *  or Calendar
+     * @param field  the field from Calendar
+     *  or SEMI_MONTH
+     * @return the rounded date
+     * @throws IllegalArgumentException if the date
+     *  is null
+     * @throws ClassCastException if the object type is not a
+     *  Date or Calendar
+     */
+    public static Date truncate(Object date, int field) {
+        if (date == null) {
+            throw new IllegalArgumentException("The date must not be null");
+        }
+        if (date instanceof Date) {
+            return truncate((Date) date, field);
+        } else if (date instanceof Calendar) {
+            return truncate((Calendar) date, field).getTime();
+        } else {
+            throw new ClassCastException("Could not truncate " + date);
+        }
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Internal calculation method.
+     * 
+     * @param val  the calendar
+     * @param field  the field constant
+     * @param round  true to round, false to truncate
+     */
+    private static void modify(Calendar val, int field, boolean round) {
+        boolean roundUp = false;
+        for (int i = 0; i < fields.length; i++) {
+            for (int j = 0; j < fields[i].length; j++) {
+                if (fields[i][j] == field) {
+                    //This is our field... we stop looping
+                    if (round && roundUp) {
+                        if (field == DateUtils.SEMI_MONTH) {
+                            //This is a special case that's hard to generalize
+                            //If the date is 1, we round up to 16, otherwise
+                            //  we subtract 15 days and add 1 month
+                            if (val.get(Calendar.DATE) == 1) {
+                                val.add(Calendar.DATE, 15);
+                            } else {
+                                val.add(Calendar.DATE, -15);
+                                val.add(Calendar.MONTH, 1);
+                            }
+                        } else {
+                            //We need at add one to this field since the
+                            //  last number causes us to round up
+                            val.add(fields[i][0], 1);
+                        }
+                    }
+                    return;
+                }
+            }
+            //We have various fields that are not easy roundings
+            int offset = 0;
+            boolean offsetSet = false;
+            //These are special types of fields that require different rounding rules
+            switch (field) {
+                case DateUtils.SEMI_MONTH:
+                    if (fields[i][0] == Calendar.DATE) {
+                        //If we're going to drop the DATE field's value,
+                        //  we want to do this our own way.
+                        //We need to subtrace 1 since the date has a minimum of 1
+                        offset = val.get(Calendar.DATE) - 1;
+                        //If we're above 15 days adjustment, that means we're in the
+                        //  bottom half of the month and should stay accordingly.
+                        if (offset >= 15) {
+                            offset -= 15;
+                        }
+                        //Record whether we're in the top or bottom half of that range
+                        roundUp = offset > 7;
+                        offsetSet = true;
+                    }
+                    break;
+                case Calendar.AM_PM:
+                    if (fields[i][0] == Calendar.HOUR) {
+                        //If we're going to drop the HOUR field's value,
+                        //  we want to do this our own way.
+                        offset = val.get(Calendar.HOUR);
+                        if (offset >= 12) {
+                            offset -= 12;
+                        }
+                        roundUp = offset > 6;
+                        offsetSet = true;
+                    }
+                    break;
+            }
+            if (!offsetSet) {
+                int min = val.getActualMinimum(fields[i][0]);
+                int max = val.getActualMaximum(fields[i][0]);
+                //Calculate the offset from the minimum allowed value
+                offset = val.get(fields[i][0]) - min;
+                //Set roundUp if this is more than half way between the minimum and maximum
+                roundUp = offset > ((max - min) / 2);
+            }
+            //We need to remove this field
+            val.add(fields[i][0], -offset);
+        }
+        throw new IllegalArgumentException("The field " + field + " is not supported");
+
+    }
+
+    // TODO: Decide whether this code is removed or goes into 2.1
+    //-----------------------------------------------------------------------
+    /*
+     * Parses a date string formatted in CVS format.
+     * 
+     * @param dateStr  the date to parse
+     * @return the parsed date
+     * @throws IllegalArgumentException if the date cannot be parsed
+    public static Calendar parseCVS(String dateStr) {
+        if (dateStr == null) {
+            throw new IllegalArgumentException("The date must not be null");
+        }
+        //Get the symbol names
+        DateFormatSymbols symbols = new DateFormatSymbols(Locale.ENGLISH);
+
+        //Prep the string to parse
+        String value = dateStr.toLowerCase().trim();
+
+        //Get the current date/time
+        Calendar now = Calendar.getInstance();
+        if (value.endsWith(" ago")) {
+            //If this was a date that was "ago" the current time...
+            //Strip out the ' ago' part
+            value = value.substring(0, value.length() - 4);
+
+            //Split the value and unit
+            int start = value.indexOf(" ");
+            if (start < 0) {
+                throw new IllegalArgumentException("Could not find space in between value and unit");
+            }
+            String unit = value.substring(start + 1);
+            value = value.substring(0, start);
+            //We support "a week", so we need to parse the value as "a"
+            int val = 0;
+            if (value.equals("a") || value.equals("an")) {
+                val = 1;
+            } else {
+                val = Integer.parseInt(value);
+            }
+
+            //Determine the unit
+            if (unit.equals("milliseconds") || unit.equals("millisecond")) {
+                now.add(Calendar.MILLISECOND, -val);
+            } else if (unit.equals("seconds") || unit.equals("second")) {
+                now.add(Calendar.SECOND, -val);
+            } else if (unit.equals("minutes") || unit.equals("minute")) {
+                now.add(Calendar.MINUTE, -val);
+            } else if (unit.equals("hours") || unit.equals("hour")) {
+                now.add(Calendar.HOUR, -val);
+            } else if (unit.equals("days") || unit.equals("day")) {
+                now.add(Calendar.DATE, -val);
+            } else if (unit.equals("weeks") || unit.equals("week")) {
+                now.add(Calendar.DATE, -val * 7);
+            } else if (unit.equals("fortnights") || unit.equals("fortnight")) {
+                now.add(Calendar.DATE, -val * 14);
+            } else if (unit.equals("months") || unit.equals("month")) {
+                now.add(Calendar.MONTH, -val);
+            } else if (unit.equals("years") || unit.equals("year")) {
+                now.add(Calendar.YEAR, -val);
+            } else {
+                throw new IllegalArgumentException("We do not understand that many units ago");
+            }
+            return now;
+        } else if (value.startsWith("last ")) {
+            //If this was the last time a certain field was met
+            //Strip out the 'last ' part
+            value = value.substring(5);
+            //Get the current date/time
+            String[] strings = symbols.getWeekdays();
+            for (int i = 0; i < strings.length; i++) {
+                if (value.equalsIgnoreCase(strings[i])) {
+                    //How many days after Sunday
+                    int daysAgo = now.get(Calendar.DAY_OF_WEEK) - i;
+                    if (daysAgo <= 0) {
+                        daysAgo += 7;
+                    }
+                    now.add(Calendar.DATE, -daysAgo);
+                    return now;
+                }
+            }
+            strings = symbols.getMonths();
+            for (int i = 0; i < strings.length; i++) {
+                if (value.equalsIgnoreCase(strings[i])) {
+                    //How many days after January
+                    int monthsAgo = now.get(Calendar.MONTH) - i;
+                    if (monthsAgo <= 0) {
+                        monthsAgo += 12;
+                    }
+                    now.add(Calendar.MONTH, -monthsAgo);
+                    return now;
+                }
+            }
+            if (value.equals("week")) {
+                now.add(Calendar.DATE, -7);
+                return now;
+            }
+            throw new IllegalArgumentException("We do not understand that last units");
+        } else if (value.equals("yesterday")) {
+            now.add(Calendar.DATE, -1);
+            return now;
+        } else if (value.equals("tomorrow")) {
+            now.add(Calendar.DATE, 1);
+            return now;
+        }
+        //Try to parse the date a number of different ways
+        for (int i = 0; i < dateFormats.length; i++) {
+            try {
+                Date datetime = dateFormats[i].parse(dateStr);
+                Calendar cal = Calendar.getInstance();
+                cal.setTime(datetime);
+                return cal;
+            } catch (ParseException pe) {
+                //we ignore this and just keep trying
+            }
+        }
+
+        throw new IllegalArgumentException("Unable to parse '" + dateStr + "'.");
+    }
+     */
+
+    //-----------------------------------------------------------------------
+    /**
+     * This constructs an Iterator that will
+     * start and stop over a date range based on the focused
+     * date and the range style.
+     *
+     * For instance, passing Thursday, July 4, 2002 and a
+     * RANGE_MONTH_SUNDAY will return an
+     * Iterator that starts with Sunday, June 30,
+     * 2002 and ends with Saturday, August 3, 2002.
+     * 
+     * @param focus  the date to work with
+     * @param rangeStyle  the style constant to use. Must be one of the range
+     * styles listed for the {@link #iterator(Calendar, int)} method.
+     *
+     * @return the date iterator
+     * @throws IllegalArgumentException if the date is null or if
+     * the rangeStyle is not 
+     */
+    public static Iterator iterator(Date focus, int rangeStyle) {
+        if (focus == null) {
+            throw new IllegalArgumentException("The date must not be null");
+        }
+        GregorianCalendar gval = new GregorianCalendar();
+        gval.setTime(focus);
+        return iterator(gval, rangeStyle);
+    }
+
+    /**
+     * 
This constructs an Iterator that will
+     * start and stop over a date range based on the focused
+     * date and the range style.
+     *
+     * For instance, passing Thursday, July 4, 2002 and a
+     * RANGE_MONTH_SUNDAY will return an
+     * Iterator that starts with Sunday, June 30,
+     * 2002 and ends with Saturday, August 3, 2002.
+     * 
+     * @param focus  the date to work with
+     * @param rangeStyle  the style constant to use. Must be one of
+     * {@link DateUtils#RANGE_MONTH_SUNDAY}, 
+     * {@link DateUtils#RANGE_MONTH_MONDAY},
+     * {@link DateUtils#RANGE_WEEK_SUNDAY},
+     * {@link DateUtils#RANGE_WEEK_MONDAY},
+     * {@link DateUtils#RANGE_WEEK_RELATIVE},
+     * {@link DateUtils#RANGE_WEEK_CENTER}
+     * @return the date iterator
+     * @throws IllegalArgumentException if the date is null
+     */
+    public static Iterator iterator(Calendar focus, int rangeStyle) {
+        if (focus == null) {
+            throw new IllegalArgumentException("The date must not be null");
+        }
+        Calendar start = null;
+        Calendar end = null;
+        int startCutoff = Calendar.SUNDAY;
+        int endCutoff = Calendar.SATURDAY;
+        switch (rangeStyle) {
+            case RANGE_MONTH_SUNDAY:
+            case RANGE_MONTH_MONDAY:
+                //Set start to the first of the month
+                start = truncate(focus, Calendar.MONTH);
+                //Set end to the last of the month
+                end = (Calendar) start.clone();
+                end.add(Calendar.MONTH, 1);
+                end.add(Calendar.DATE, -1);
+                //Loop start back to the previous sunday or monday
+                if (rangeStyle == RANGE_MONTH_MONDAY) {
+                    startCutoff = Calendar.MONDAY;
+                    endCutoff = Calendar.SUNDAY;
+                }
+                break;
+            case RANGE_WEEK_SUNDAY:
+            case RANGE_WEEK_MONDAY:
+            case RANGE_WEEK_RELATIVE:
+            case RANGE_WEEK_CENTER:
+                //Set start and end to the current date
+                start = truncate(focus, Calendar.DATE);
+                end = truncate(focus, Calendar.DATE);
+                switch (rangeStyle) {
+                    case RANGE_WEEK_SUNDAY:
+                        //already set by default
+                        break;
+                    case RANGE_WEEK_MONDAY:
+                        startCutoff = Calendar.MONDAY;
+                        endCutoff = Calendar.SUNDAY;
+                        break;
+                    case RANGE_WEEK_RELATIVE:
+                        startCutoff = focus.get(Calendar.DAY_OF_WEEK);
+                        endCutoff = startCutoff - 1;
+                        break;
+                    case RANGE_WEEK_CENTER:
+                        startCutoff = focus.get(Calendar.DAY_OF_WEEK) - 3;
+                        endCutoff = focus.get(Calendar.DAY_OF_WEEK) + 3;
+                        break;
+                }
+                break;
+            default:
+                throw new IllegalArgumentException("The range style " + rangeStyle + " is not valid.");
+        }
+        if (startCutoff < Calendar.SUNDAY) {
+            startCutoff += 7;
+        }
+        if (startCutoff > Calendar.SATURDAY) {
+            startCutoff -= 7;
+        }
+        if (endCutoff < Calendar.SUNDAY) {
+            endCutoff += 7;
+        }
+        if (endCutoff > Calendar.SATURDAY) {
+            endCutoff -= 7;
+        }
+        while (start.get(Calendar.DAY_OF_WEEK) != startCutoff) {
+            start.add(Calendar.DATE, -1);
+        }
+        while (end.get(Calendar.DAY_OF_WEEK) != endCutoff) {
+            end.add(Calendar.DATE, 1);
+        }
+        return new DateIterator(start, end);
+    }
+
+    /**
+     * 
This constructs an Iterator that will
+     * start and stop over a date range based on the focused
+     * date and the range style.
+     *
+     * For instance, passing Thursday, July 4, 2002 and a
+     * RANGE_MONTH_SUNDAY will return an
+     * Iterator that starts with Sunday, June 30,
+     * 2002 and ends with Saturday, August 3, 2002.
+     * 
+     * @param focus  the date to work with, either
+     *  Date or Calendar
+     * @param rangeStyle  the style constant to use. Must be one of the range
+     * styles listed for the {@link #iterator(Calendar, int)} method.
+     * @return the date iterator
+     * @throws IllegalArgumentException if the date
+     *  is null
+     * @throws ClassCastException if the object type is
+     *  not a Date or Calendar
+     */
+    public static Iterator iterator(Object focus, int rangeStyle) {
+        if (focus == null) {
+            throw new IllegalArgumentException("The date must not be null");
+        }
+        if (focus instanceof Date) {
+            return iterator((Date) focus, rangeStyle);
+        } else if (focus instanceof Calendar) {
+            return iterator((Calendar) focus, rangeStyle);
+        } else {
+            throw new ClassCastException("Could not iterate based on " + focus);
+        }
+    }
+
+    /**
+     * Date iterator.
+     */
+    static class DateIterator implements Iterator {
+        private final Calendar endFinal;
+        private final Calendar spot;
+        
+        DateIterator(Calendar startFinal, Calendar endFinal) {
+            super();
+            this.endFinal = endFinal;
+            spot = startFinal;
+            spot.add(Calendar.DATE, -1);
+        }
+
+        public boolean hasNext() {
+            return spot.before(endFinal);
+        }
+
+        public Object next() {
+            if (spot.equals(endFinal)) {
+                throw new NoSuchElementException();
+            }
+            spot.add(Calendar.DATE, 1);
+            return spot.clone();
+        }
+
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+    }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/time/DurationFormatUtils.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/time/DurationFormatUtils.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/time/DurationFormatUtils.java	30 Aug 2012 16:24:43 -0000	1.1
@@ -0,0 +1,202 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang.time;
+
+/**
+ * Duration formatting utilites and constants.
+ *
+ * @author Apache Ant - DateUtils
+ * @author Stephane Bailliez
+ * @author Stefan Bodewig
+ * @author Stephen Colebourne
+ * @author Gary Gregory
+ * @since 2.0
+ * @version $Id: DurationFormatUtils.java,v 1.1 2012/08/30 16:24:43 marcin Exp $
+ */
+class DurationFormatUtils {
+    // TODO: Make class public once methods can fully select which fields to output
+
+    /**
+     * Pattern used with FastDateFormat and SimpleDateFormat  for the ISO8601 
+     * date time extended format used in durations.
+     * 
+     * @see org.apache.commons.lang.time.FastDateFormat
+     * @see java.text.SimpleDateFormat
+     */
+    public static final String ISO_EXTENDED_FORMAT_PATTERN = "'P'yyyy'Y'M'M'd'DT'H'H'm'M's.S'S'";
+
+    /**
+     * ISO8601 formatter for the date time extended format used in durations, 
+     * with XML Schema durations particularly in mind.
+     * 
+     * This format represents the Gregorian year, month, day, hour, minute, and second components defined 
+     * in � 5.5.3.2 of ISO 8601, respectively. These components are ordered in their significance by their order 
+     * of appearance i.e. as year, month, day, hour, minute, and second.
+     * 
+     * The ISO8601 extended format PnYnMnDTnHnMnS, where nY 
+     * represents the number of years, nM the number of months, nD the number of days, 
+     * 'T' is the date/time separator, nH the number of hours, nM the number of minutes and 
+     * nS the number of seconds. The number of seconds can include decimal digits to arbitrary precision.
+     * 
+     * @see #ISO_EXTENDED_FORMAT_PATTERN
+     * @see http://www.w3.org/TR/xmlschema-2/#duration
+     */
+    public static final FastDateFormat ISO_EXTENDED_FORMAT =
+        FastDateFormat.getInstance(ISO_EXTENDED_FORMAT_PATTERN);
+
+    /**
+     * Get the time gap as a string.
+     * 
+     * The format used is ISO8601-like:
+     * hours:minutes:seconds.milliseconds.
+     * 
+     * @param millis  the duration to format
+     * @return the time as a String
+     */
+    public static String formatISO(long millis) {
+        int hours, minutes, seconds, milliseconds;
+        hours = (int) (millis / DateUtils.MILLIS_IN_HOUR);
+        millis = millis - (hours * DateUtils.MILLIS_IN_HOUR);
+        minutes = (int) (millis / DateUtils.MILLIS_IN_MINUTE);
+        millis = millis - (minutes * DateUtils.MILLIS_IN_MINUTE);
+        seconds = (int) (millis / DateUtils.MILLIS_IN_SECOND);
+        millis = millis - (seconds * DateUtils.MILLIS_IN_SECOND);
+        milliseconds = (int) millis;
+
+        StringBuffer buf = new StringBuffer(32);
+        buf.append(hours);
+        buf.append(':');
+        buf.append((char) (minutes / 10 + '0'));
+        buf.append((char) (minutes % 10 + '0'));
+        buf.append(':');
+        buf.append((char) (seconds / 10 + '0'));
+        buf.append((char) (seconds % 10 + '0'));
+        buf.append('.');
+        if (milliseconds < 10) {
+            buf.append('0').append('0');
+        } else if (milliseconds < 100) {
+            buf.append('0');
+        }
+        buf.append(milliseconds);
+        return buf.toString();
+    }
+
+    /**
+     * Format an elapsed time into a plurialization correct string.
+     * It is limited only to report elapsed time in minutes and
+     * seconds and has the following behavior.
+     *
+     * 
+     *  - minutes are not displayed when 
0 (ie:
+     *   "45 seconds") .
+     *  - seconds are always displayed in plural form (ie
+     *   "0 seconds" or "10 seconds") except
+     *   for 
1 (ie "1 second") 
+     *  
+     * 
+     * @param millis  the elapsed time to report in milliseconds
+     * @return the formatted text in minutes/seconds
+     */
+    public static String formatWords(
+        long millis,
+        boolean supressLeadingZeroElements,
+        boolean supressTrailingZeroElements) {
+        long[] values = new long[4];
+        values[0] = millis / DateUtils.MILLIS_IN_DAY;
+        values[1] = (millis / DateUtils.MILLIS_IN_HOUR) % 24;
+        values[2] = (millis / DateUtils.MILLIS_IN_MINUTE) % 60;
+        values[3] = (millis / DateUtils.MILLIS_IN_SECOND) % 60;
+        String[] fieldsOne = { " day ", " hour ", " minute ", " second" };
+        String[] fieldsPlural = { " days ", " hours ", " minutes ", " seconds" };
+
+        StringBuffer buf = new StringBuffer(64);
+        boolean valueOutput = false;
+
+        for (int i = 0; i < 4; i++) {
+            long value = values[i];
+            if (value == 0) {
+                // handle zero
+                if (valueOutput) {
+                    if (supressTrailingZeroElements == false) {
+                        buf.append('0').append(fieldsPlural[i]);
+                    }
+                } else {
+                    if (supressLeadingZeroElements == false) {
+                        buf.append('0').append(fieldsPlural[i]);
+                    }
+                }
+            } else if (value == 1) {
+                // one
+                valueOutput = true;
+                buf.append('1').append(fieldsOne[i]);
+            } else {
+                // other
+                valueOutput = true;
+                buf.append(value).append(fieldsPlural[i]);
+            }
+        }
+
+        return buf.toString().trim();
+    }
+
+    /**
+     * DurationFormatUtils instances should NOT be constructed in standard programming.
+     *
+     * This constructor is public to permit tools that require a JavaBean instance
+     * to operate.
+     */
+    public DurationFormatUtils() {
+    }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/time/FastDateFormat.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/time/FastDateFormat.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/time/FastDateFormat.java	30 Aug 2012 16:24:43 -0000	1.1
@@ -0,0 +1,1373 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang.time;
+
+import java.text.DateFormat;
+import java.text.DateFormatSymbols;
+import java.text.FieldPosition;
+import java.text.Format;
+import java.text.ParsePosition;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.Date;
+import java.util.GregorianCalendar;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Locale;
+import java.util.Map;
+import java.util.TimeZone;
+
+/**
+ * FastDateFormat is a fast and thread-safe version of
+ * {@link java.text.SimpleDateFormat}.
+ * 
+ * This class can be used as a direct replacement to
+ * SimpleDateFormat in most formatting situations.
+ * This class is especially useful in multi-threaded server environments.
+ * SimpleDateFormat is not thread-safe in any JDK version,
+ * nor will it be as Sun have closed the bug/RFE.
+ * 
+ *
+ * Only formatting is supported, but all patterns are compatible with
+ * SimpleDateFormat (except time zones - see below).
+ *
+ * Java 1.4 introduced a new pattern letter, 'Z', to represent
+ * time zones in RFC822 format (eg. +0800 or -1100).
+ * This pattern letter can be used here (on all JDK versions).
+ *
+ * In addition, the pattern 'ZZ' has been made to represent
+ * ISO8601 full format time zones (eg. +08:00 or -11:00).
+ * This introduces a minor incompatability with Java 1.4, but at a gain of
+ * useful functionality.
+ *
+ * @author TeaTrove project
+ * @author Brian S O'Neill
+ * @author Sean Schofield
+ * @author Gary Gregory
+ * @author Stephen Colebourne
+ * @since 2.0
+ * @version $Id: FastDateFormat.java,v 1.1 2012/08/30 16:24:43 marcin Exp $
+ */
+public class FastDateFormat extends Format {
+    // A lot of the speed in this class comes from caching, but some comes
+    // from the special int to StringBuffer conversion.
+    //
+    // The following produces a padded 2 digit number:
+    //   buffer.append((char)(value / 10 + '0'));
+    //   buffer.append((char)(value % 10 + '0'));
+    //
+    // Note that the fastest append to StringBuffer is a single char (used here).
+    // Note that Integer.toString() is not called, the conversion is simply
+    // taking the value and adding (mathematically) the ASCII value for '0'.
+    // So, don't change this code! It works and is very fast.
+    
+    /**
+     * FULL locale dependent date or time style.
+     */
+    public static final int FULL = DateFormat.FULL;
+    /**
+     * LONG locale dependent date or time style.
+     */
+    public static final int LONG = DateFormat.LONG;
+    /**
+     * MEDIUM locale dependent date or time style.
+     */
+    public static final int MEDIUM = DateFormat.MEDIUM;
+    /**
+     * SHORT locale dependent date or time style.
+     */
+    public static final int SHORT = DateFormat.SHORT;
+    
+    // package scoped as used by inner class
+    static final double LOG_10 = Math.log(10);
+
+    private static String cDefaultPattern;
+
+    private static Map cInstanceCache = new HashMap(7);
+    private static Map cDateInstanceCache = new HashMap(7);
+    private static Map cTimeInstanceCache = new HashMap(7);
+    private static Map cDateTimeInstanceCache = new HashMap(7);
+    private static Map cTimeZoneDisplayCache = new HashMap(7);
+
+    /**
+     * The pattern.
+     */
+    private final String mPattern;
+    /**
+     * The time zone.
+     */
+    private final TimeZone mTimeZone;
+    /**
+     * Whether the time zone overrides any on Calendars.
+     */
+    private final boolean mTimeZoneForced;
+    /**
+     * The locale.
+     */
+    private final Locale mLocale;
+    /**
+     * Whether the locale overrides the default.
+     */
+    private final boolean mLocaleForced;
+    /**
+     * The parsed rules.
+     */
+    private Rule[] mRules;
+    /**
+     * The estimated maximum length.
+     */
+    private int mMaxLengthEstimate;
+
+    //-----------------------------------------------------------------------
+    /**
+     * Gets a formatter instance using the default pattern in the
+     * default locale.
+     * 
+     * @return a date/time formatter
+     */
+    public static FastDateFormat getInstance() {
+        return getInstance(getDefaultPattern(), null, null);
+    }
+
+    /**
+     * Gets a formatter instance using the specified pattern in the
+     * default locale.
+     * 
+     * @param pattern  {@link java.text.SimpleDateFormat} compatible
+     *  pattern
+     * @return a pattern based date/time formatter
+     * @throws IllegalArgumentException if pattern is invalid
+     */
+    public static FastDateFormat getInstance(String pattern) {
+        return getInstance(pattern, null, null);
+    }
+
+    /**
+     * Gets a formatter instance using the specified pattern and
+     * time zone.
+     * 
+     * @param pattern  {@link java.text.SimpleDateFormat} compatible
+     *  pattern
+     * @param timeZone  optional time zone, overrides time zone of
+     *  formatted date
+     * @return a pattern based date/time formatter
+     * @throws IllegalArgumentException if pattern is invalid
+     */
+    public static FastDateFormat getInstance(String pattern, TimeZone timeZone) {
+        return getInstance(pattern, timeZone, null);
+    }
+
+    /**
+     * Gets a formatter instance using the specified pattern and
+     * locale.
+     * 
+     * @param pattern  {@link java.text.SimpleDateFormat} compatible
+     *  pattern
+     * @param locale  optional locale, overrides system locale
+     * @return a pattern based date/time formatter
+     * @throws IllegalArgumentException if pattern is invalid
+     */
+    public static FastDateFormat getInstance(String pattern, Locale locale) {
+        return getInstance(pattern, null, locale);
+    }
+
+    /**
+     * Gets a formatter instance using the specified pattern, time zone
+     * and locale.
+     * 
+     * @param pattern  {@link java.text.SimpleDateFormat} compatible
+     *  pattern
+     * @param timeZone  optional time zone, overrides time zone of
+     *  formatted date
+     * @param locale  optional locale, overrides system locale
+     * @return a pattern based date/time formatter
+     * @throws IllegalArgumentException if pattern is invalid
+     *  or null
+     */
+    public static synchronized FastDateFormat getInstance(String pattern, TimeZone timeZone, Locale locale) {
+        FastDateFormat emptyFormat = new FastDateFormat(pattern, timeZone, locale);
+        FastDateFormat format = (FastDateFormat) cInstanceCache.get(emptyFormat);
+        if (format == null) {
+            format = emptyFormat;
+            format.init();  // convert shell format into usable one
+            cInstanceCache.put(format, format);  // this is OK!
+        }
+        return format;
+    }
+
+    /**
+     * Gets a date formatter instance using the specified style, time
+     * zone and locale.
+     * 
+     * @param style  date style: FULL, LONG, MEDIUM, or SHORT
+     * @param timeZone  optional time zone, overrides time zone of
+     *  formatted date
+     * @param locale  optional locale, overrides system locale
+     * @return a localized standard date formatter
+     * @throws IllegalArgumentException if the Locale has no date
+     *  pattern defined
+     */
+    public static synchronized FastDateFormat getDateInstance(int style, TimeZone timeZone, Locale locale) {
+        Object key = new Integer(style);
+        if (timeZone != null) {
+            key = new Pair(key, timeZone);
+        }
+        if (locale == null) {
+            key = new Pair(key, locale);
+        }
+
+        FastDateFormat format = (FastDateFormat) cDateInstanceCache.get(key);
+        if (format == null) {
+            if (locale == null) {
+                locale = Locale.getDefault();
+            }
+
+            try {
+                SimpleDateFormat formatter = (SimpleDateFormat) DateFormat.getDateInstance(style, locale);
+                String pattern = formatter.toPattern();
+                format = getInstance(pattern, timeZone, locale);
+                cDateInstanceCache.put(key, format);
+                
+            } catch (ClassCastException ex) {
+                throw new IllegalArgumentException("No date pattern for locale: " + locale);
+            }
+        }
+        return format;
+    }
+
+    /**
+     * Gets a time formatter instance using the specified style, time
+     * zone and locale.
+     * 
+     * @param style  time style: FULL, LONG, MEDIUM, or SHORT
+     * @param timeZone  optional time zone, overrides time zone of
+     *  formatted time
+     * @param locale  optional locale, overrides system locale
+     * @return a localized standard time formatter
+     * @throws IllegalArgumentException if the Locale has no time
+     *  pattern defined
+     */
+    public static synchronized FastDateFormat getTimeInstance(int style, TimeZone timeZone, Locale locale) {
+        Object key = new Integer(style);
+        if (timeZone != null) {
+            key = new Pair(key, timeZone);
+        }
+        if (locale != null) {
+            key = new Pair(key, locale);
+        }
+
+        FastDateFormat format = (FastDateFormat) cTimeInstanceCache.get(key);
+        if (format == null) {
+            if (locale == null) {
+                locale = Locale.getDefault();
+            }
+
+            try {
+                SimpleDateFormat formatter = (SimpleDateFormat) DateFormat.getTimeInstance(style, locale);
+                String pattern = formatter.toPattern();
+                format = getInstance(pattern, timeZone, locale);
+                cTimeInstanceCache.put(key, format);
+            
+            } catch (ClassCastException ex) {
+                throw new IllegalArgumentException("No date pattern for locale: " + locale);
+            }
+        }
+        return format;
+    }
+
+    /**
+     * Gets a date/time formatter instance using the specified style,
+     * time zone and locale.
+     * 
+     * @param dateStyle  date style: FULL, LONG, MEDIUM, or SHORT
+     * @param timeStyle  time style: FULL, LONG, MEDIUM, or SHORT
+     * @param timeZone  optional time zone, overrides time zone of
+     *  formatted date
+     * @param locale  optional locale, overrides system locale
+     * @return a localized standard date/time formatter
+     * @throws IllegalArgumentException if the Locale has no date/time
+     *  pattern defined
+     */
+    public static synchronized FastDateFormat getDateTimeInstance(
+            int dateStyle, int timeStyle, TimeZone timeZone, Locale locale) {
+
+        Object key = new Pair(new Integer(dateStyle), new Integer(timeStyle));
+        if (timeZone != null) {
+            key = new Pair(key, timeZone);
+        }
+        if (locale != null) {
+            key = new Pair(key, locale);
+        }
+
+        FastDateFormat format = (FastDateFormat) cDateTimeInstanceCache.get(key);
+        if (format == null) {
+            if (locale == null) {
+                locale = Locale.getDefault();
+            }
+
+            try {
+                SimpleDateFormat formatter = (SimpleDateFormat) DateFormat.getDateTimeInstance(dateStyle, timeStyle, locale);
+                String pattern = formatter.toPattern();
+                format = getInstance(pattern, timeZone, locale);
+                cDateTimeInstanceCache.put(key, format);
+                
+            } catch (ClassCastException ex) {
+                throw new IllegalArgumentException("No date time pattern for locale: " + locale);
+            }
+        }
+        return format;
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * Gets the time zone display name, using a cache for performance.
+     * 
+     * @param tz  the zone to query
+     * @param daylight  true if daylight savings
+     * @param style  the style to use TimeZone.LONG
+     *  or TimeZone.SHORT
+     * @param locale  the locale to use
+     * @return the textual name of the time zone
+     */
+    static synchronized String getTimeZoneDisplay(TimeZone tz, boolean daylight, int style, Locale locale) {
+        Object key = new TimeZoneDisplayKey(tz, daylight, style, locale);
+        String value = (String) cTimeZoneDisplayCache.get(key);
+        if (value == null) {
+            // This is a very slow call, so cache the results.
+            value = tz.getDisplayName(daylight, style, locale);
+            cTimeZoneDisplayCache.put(key, value);
+        }
+        return value;
+    }
+
+    /**
+     * Gets the default pattern.
+     * 
+     * @return the default pattern
+     */
+    private static synchronized String getDefaultPattern() {
+        if (cDefaultPattern == null) {
+            cDefaultPattern = new SimpleDateFormat().toPattern();
+        }
+        return cDefaultPattern;
+    }
+
+    // Constructor
+    //-----------------------------------------------------------------------
+    /**
+     * Constructs a new FastDateFormat.
+     * 
+     * @param pattern  {@link java.text.SimpleDateFormat} compatible
+     *  pattern
+     * @param timeZone  time zone to use, null means use
+     *  default for Date and value within for
+     *  Calendar
+     * @param locale  locale, null means use system
+     *  default
+     * @throws IllegalArgumentException if pattern is invalid or
+     *  null
+     */
+    protected FastDateFormat(String pattern, TimeZone timeZone, Locale locale) {
+        super();
+        if (pattern == null) {
+            throw new IllegalArgumentException("The pattern must not be null");
+        }
+        mPattern = pattern;
+        
+        mTimeZoneForced = (timeZone != null);
+        if (timeZone == null) {
+            timeZone = TimeZone.getDefault();
+        }
+        mTimeZone = timeZone;
+        
+        mLocaleForced = (locale != null);
+        if (locale == null) {
+            locale = Locale.getDefault();
+        }
+        mLocale = locale;
+    }
+
+    /**
+     * Initialise the instance for first use.
+     */
+    protected void init() {
+        List rulesList = parsePattern();
+        mRules = (Rule[]) rulesList.toArray(new Rule[rulesList.size()]);
+
+        int len = 0;
+        for (int i=mRules.length; --i >= 0; ) {
+            len += mRules[i].estimateLength();
+        }
+
+        mMaxLengthEstimate = len;
+    }
+
+    // Parse the pattern
+    //-----------------------------------------------------------------------
+    /**
+     * Returns a list of Rules given a pattern.
+     * 
+     * @return a List of Rule objects
+     * @throws IllegalArgumentException if pattern is invalid
+     */
+    protected List parsePattern() {
+        DateFormatSymbols symbols = new DateFormatSymbols(mLocale);
+        List rules = new ArrayList();
+
+        String[] ERAs = symbols.getEras();
+        String[] months = symbols.getMonths();
+        String[] shortMonths = symbols.getShortMonths();
+        String[] weekdays = symbols.getWeekdays();
+        String[] shortWeekdays = symbols.getShortWeekdays();
+        String[] AmPmStrings = symbols.getAmPmStrings();
+
+        int length = mPattern.length();
+        int[] indexRef = new int[1];
+
+        for (int i = 0; i < length; i++) {
+            indexRef[0] = i;
+            String token = parseToken(mPattern, indexRef);
+            i = indexRef[0];
+
+            int tokenLen = token.length();
+            if (tokenLen == 0) {
+                break;
+            }
+
+            Rule rule;
+            char c = token.charAt(0);
+
+            switch (c) {
+            case 'G': // era designator (text)
+                rule = new TextField(Calendar.ERA, ERAs);
+                break;
+            case 'y': // year (number)
+                if (tokenLen >= 4) {
+                    rule = UnpaddedNumberField.INSTANCE_YEAR;
+                } else {
+                    rule = TwoDigitYearField.INSTANCE;
+                }
+                break;
+            case 'M': // month in year (text and number)
+                if (tokenLen >= 4) {
+                    rule = new TextField(Calendar.MONTH, months);
+                } else if (tokenLen == 3) {
+                    rule = new TextField(Calendar.MONTH, shortMonths);
+                } else if (tokenLen == 2) {
+                    rule = TwoDigitMonthField.INSTANCE;
+                } else {
+                    rule = UnpaddedMonthField.INSTANCE;
+                }
+                break;
+            case 'd': // day in month (number)
+                rule = selectNumberRule(Calendar.DAY_OF_MONTH, tokenLen);
+                break;
+            case 'h': // hour in am/pm (number, 1..12)
+                rule = new TwelveHourField(selectNumberRule(Calendar.HOUR, tokenLen));
+                break;
+            case 'H': // hour in day (number, 0..23)
+                rule = selectNumberRule(Calendar.HOUR_OF_DAY, tokenLen);
+                break;
+            case 'm': // minute in hour (number)
+                rule = selectNumberRule(Calendar.MINUTE, tokenLen);
+                break;
+            case 's': // second in minute (number)
+                rule = selectNumberRule(Calendar.SECOND, tokenLen);
+                break;
+            case 'S': // millisecond (number)
+                rule = selectNumberRule(Calendar.MILLISECOND, tokenLen);
+                break;
+            case 'E': // day in week (text)
+                rule = new TextField(Calendar.DAY_OF_WEEK, tokenLen < 4 ? shortWeekdays : weekdays);
+                break;
+            case 'D': // day in year (number)
+                rule = selectNumberRule(Calendar.DAY_OF_YEAR, tokenLen);
+                break;
+            case 'F': // day of week in month (number)
+                rule = selectNumberRule(Calendar.DAY_OF_WEEK_IN_MONTH, tokenLen);
+                break;
+            case 'w': // week in year (number)
+                rule = selectNumberRule(Calendar.WEEK_OF_YEAR, tokenLen);
+                break;
+            case 'W': // week in month (number)
+                rule = selectNumberRule(Calendar.WEEK_OF_MONTH, tokenLen);
+                break;
+            case 'a': // am/pm marker (text)
+                rule = new TextField(Calendar.AM_PM, AmPmStrings);
+                break;
+            case 'k': // hour in day (1..24)
+                rule = new TwentyFourHourField(selectNumberRule(Calendar.HOUR_OF_DAY, tokenLen));
+                break;
+            case 'K': // hour in am/pm (0..11)
+                rule = selectNumberRule(Calendar.HOUR, tokenLen);
+                break;
+            case 'z': // time zone (text)
+                if (tokenLen >= 4) {
+                    rule = new TimeZoneNameRule(mTimeZone, mTimeZoneForced, mLocale, TimeZone.LONG);
+                } else {
+                    rule = new TimeZoneNameRule(mTimeZone, mTimeZoneForced, mLocale, TimeZone.SHORT);
+                }
+                break;
+            case 'Z': // time zone (value)
+                if (tokenLen == 1) {
+                    rule = TimeZoneNumberRule.INSTANCE_NO_COLON;
+                } else {
+                    rule = TimeZoneNumberRule.INSTANCE_COLON;
+                }
+                break;
+            case '\'': // literal text
+                String sub = token.substring(1);
+                if (sub.length() == 1) {
+                    rule = new CharacterLiteral(sub.charAt(0));
+                } else {
+                    rule = new StringLiteral(sub);
+                }
+                break;
+            default:
+                throw new IllegalArgumentException("Illegal pattern component: " + token);
+            }
+
+            rules.add(rule);
+        }
+
+        return rules;
+    }
+
+    /**
+     * Performs the parsing of tokens.
+     * 
+     * @param pattern  the pattern
+     * @param indexRef  index references
+     * @return parsed token
+     */
+    protected String parseToken(String pattern, int[] indexRef) {
+        StringBuffer buf = new StringBuffer();
+
+        int i = indexRef[0];
+        int length = pattern.length();
+
+        char c = pattern.charAt(i);
+        if (c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z') {
+            // Scan a run of the same character, which indicates a time
+            // pattern.
+            buf.append(c);
+
+            while (i + 1 < length) {
+                char peek = pattern.charAt(i + 1);
+                if (peek == c) {
+                    buf.append(c);
+                    i++;
+                } else {
+                    break;
+                }
+            }
+        } else {
+            // This will identify token as text.
+            buf.append('\'');
+
+            boolean inLiteral = false;
+
+            for (; i < length; i++) {
+                c = pattern.charAt(i);
+
+                if (c == '\'') {
+                    if (i + 1 < length && pattern.charAt(i + 1) == '\'') {
+                        // '' is treated as escaped '
+                        i++;
+                        buf.append(c);
+                    } else {
+                        inLiteral = !inLiteral;
+                    }
+                } else if (!inLiteral &&
+                         (c >= 'A' && c <= 'Z' || c >= 'a' && c <= 'z')) {
+                    i--;
+                    break;
+                } else {
+                    buf.append(c);
+                }
+            }
+        }
+
+        indexRef[0] = i;
+        return buf.toString();
+    }
+
+    /**
+     * Gets an appropriate rule for the padding required.
+     * 
+     * @param field  the field to get a rule for
+     * @param padding  the padding required
+     * @return a new rule with the correct padding
+     */
+    protected NumberRule selectNumberRule(int field, int padding) {
+        switch (padding) {
+        case 1:
+            return new UnpaddedNumberField(field);
+        case 2:
+            return new TwoDigitNumberField(field);
+        default:
+            return new PaddedNumberField(field, padding);
+        }
+    }
+
+    // Format methods
+    //-----------------------------------------------------------------------
+    /**
+     * Format either a Date or a
+     * Calendar object.
+     * 
+     * @param obj  the object to format
+     * @param toAppendTo  the buffer to append to
+     * @param pos  the position - ignored
+     * @return the buffer passed in
+     */
+    public StringBuffer format(Object obj, StringBuffer toAppendTo, FieldPosition pos) {
+        if (obj instanceof Date) {
+            return format((Date) obj, toAppendTo);
+        } else if (obj instanceof Calendar) {
+            return format((Calendar) obj, toAppendTo);
+        } else {
+            throw new IllegalArgumentException("Unknown class: " +
+                (obj == null ? "" : obj.getClass().getName()));
+        }
+    }
+
+    /**
+     * Formats a Date object.
+     * 
+     * @param date  the date to format
+     * @return the formatted string
+     */
+    public String format(Date date) {
+        Calendar c = new GregorianCalendar(mTimeZone);
+        c.setTime(date);
+        return applyRules(c, new StringBuffer(mMaxLengthEstimate)).toString();
+    }
+
+    /**
+     * Formats a Calendar object.
+     * 
+     * @param calendar  the calendar to format
+     * @return the formatted string
+     */
+    public String format(Calendar calendar) {
+        return format(calendar, new StringBuffer(mMaxLengthEstimate)).toString();
+    }
+
+    /**
+     * Formats a Date object into the
+     * supplied StringBuffer.
+     * 
+     * @param date  the date to format
+     * @param buf  the buffer to format into
+     * @return the specified string buffer
+     */
+    public StringBuffer format(Date date, StringBuffer buf) {
+        Calendar c = new GregorianCalendar(mTimeZone);
+        c.setTime(date);
+        return applyRules(c, buf);
+    }
+
+    /**
+     * Formats a Calendar object into the
+     * supplied StringBuffer.
+     * 
+     * @param calendar  the calendar to format
+     * @param buf  the buffer to format into
+     * @return the specified string buffer
+     */
+    public StringBuffer format(Calendar calendar, StringBuffer buf) {
+        if (mTimeZoneForced) {
+            calendar = (Calendar) calendar.clone();
+            calendar.setTimeZone(mTimeZone);
+        }
+        return applyRules(calendar, buf);
+    }
+
+    /**
+     * Performs the formatting by applying the rules to the
+     * specified calendar.
+     * 
+     * @param calendar  the calendar to format
+     * @param buf  the buffer to format into
+     * @return the specified string buffer
+     */
+    protected StringBuffer applyRules(Calendar calendar, StringBuffer buf) {
+        Rule[] rules = mRules;
+        int len = mRules.length;
+        for (int i = 0; i < len; i++) {
+            rules[i].appendTo(buf, calendar);
+        }
+        return buf;
+    }
+
+    // Parsing
+    //-----------------------------------------------------------------------
+    /**
+     * Parsing not supported.
+     * 
+     * @param source  the string to parse
+     * @param pos  the parsing position
+     * @return null as not supported
+     */
+    public Object parseObject(String source, ParsePosition pos) {
+        pos.setIndex(0);
+        pos.setErrorIndex(0);
+        return null;
+    }
+    
+    // Accessors
+    //-----------------------------------------------------------------------
+    /**
+     * Gets the pattern used by this formatter.
+     * 
+     * @return the pattern, {@link java.text.SimpleDateFormat} compatible
+     */
+    public String getPattern() {
+        return mPattern;
+    }
+
+    /**
+     * Gets the time zone used by this formatter.
+     *
+     * This zone is always used for Date formatting.
+     * If a Calendar is passed in to be formatted, the
+     * time zone on that may be used depending on
+     * {@link #getTimeZoneOverridesCalendar()}.
+     * 
+     * @return the time zone
+     */
+    public TimeZone getTimeZone() {
+        return mTimeZone;
+    }
+
+    /**
+     * Returns true if the time zone of the
+     * calendar overrides the time zone of the formatter.
+     * 
+     * @return true if time zone of formatter
+     *  overridden for calendars
+     */
+    public boolean getTimeZoneOverridesCalendar() {
+        return mTimeZoneForced;
+    }
+
+    /**
+     * Gets the locale used by this formatter.
+     * 
+     * @return the locale
+     */
+    public Locale getLocale() {
+        return mLocale;
+    }
+
+    /**
+     * Gets  an estimate for the maximum string length that the
+     * formatter will produce.
+     *
+     * The actual formatted length will almost always be less than or
+     * equal to this amount.
+     * 
+     * @return the maximum formatted length
+     */
+    public int getMaxLengthEstimate() {
+        return mMaxLengthEstimate;
+    }
+
+    // Basics
+    //-----------------------------------------------------------------------
+    /**
+     * Compare two objects for equality.
+     * 
+     * @param obj  the object to compare to
+     * @return true if equal
+     */
+    public boolean equals(Object obj) {
+        if (obj instanceof FastDateFormat == false) {
+            return false;
+        }
+        FastDateFormat other = (FastDateFormat) obj;
+        if (
+            (mPattern == other.mPattern || mPattern.equals(other.mPattern)) &&
+            (mTimeZone == other.mTimeZone || mTimeZone.equals(other.mTimeZone)) &&
+            (mLocale == other.mLocale || mLocale.equals(other.mLocale)) &&
+            (mTimeZoneForced == other.mTimeZoneForced) &&
+            (mLocaleForced == other.mLocaleForced)
+            ) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * A suitable hashcode.
+     * 
+     * @return a hashcode compatable with equals
+     */
+    public int hashCode() {
+        int total = 0;
+        total += mPattern.hashCode();
+        total += mTimeZone.hashCode();
+        total += (mTimeZoneForced ? 1 : 0);
+        total += mLocale.hashCode();
+        total += (mLocaleForced ? 1 : 0);
+        return total;
+    }
+
+    /**
+     * Gets a debugging string version of this formatter.
+     * 
+     * @return a debugging string
+     */
+    public String toString() {
+        return "FastDateFormat[" + mPattern + "]";
+    }
+    
+    // Rules
+    //-----------------------------------------------------------------------
+    /**
+     * Inner class defining a rule.
+     */
+    private interface Rule {
+        int estimateLength();
+        void appendTo(StringBuffer buffer, Calendar calendar);
+    }
+
+    /**
+     * Inner class defining a numeric rule.
+     */
+    private interface NumberRule extends Rule {
+        void appendTo(StringBuffer buffer, int value);
+    }
+
+    /**
+     * Inner class to output a constant single character.
+     */
+    private static class CharacterLiteral implements Rule {
+        private final char mValue;
+
+        CharacterLiteral(char value) {
+            mValue = value;
+        }
+
+        public int estimateLength() {
+            return 1;
+        }
+
+        public void appendTo(StringBuffer buffer, Calendar calendar) {
+            buffer.append(mValue);
+        }
+    }
+
+    /**
+     * Inner class to output a constant string.
+     */
+    private static class StringLiteral implements Rule {
+        private final String mValue;
+
+        StringLiteral(String value) {
+            mValue = value;
+        }
+
+        public int estimateLength() {
+            return mValue.length();
+        }
+
+        public void appendTo(StringBuffer buffer, Calendar calendar) {
+            buffer.append(mValue);
+        }
+    }
+
+    /**
+     * Inner class to output one of a set of values.
+     */
+    private static class TextField implements Rule {
+        private final int mField;
+        private final String[] mValues;
+
+        TextField(int field, String[] values) {
+            mField = field;
+            mValues = values;
+        }
+
+        public int estimateLength() {
+            int max = 0;
+            for (int i=mValues.length; --i >= 0; ) {
+                int len = mValues[i].length();
+                if (len > max) {
+                    max = len;
+                }
+            }
+            return max;
+        }
+
+        public void appendTo(StringBuffer buffer, Calendar calendar) {
+            buffer.append(mValues[calendar.get(mField)]);
+        }
+    }
+
+    /**
+     * Inner class to output an unpadded number.
+     */
+    private static class UnpaddedNumberField implements NumberRule {
+        static final UnpaddedNumberField INSTANCE_YEAR = new UnpaddedNumberField(Calendar.YEAR);
+        
+        private final int mField;
+
+        UnpaddedNumberField(int field) {
+            mField = field;
+        }
+
+        public int estimateLength() {
+            return 4;
+        }
+
+        public void appendTo(StringBuffer buffer, Calendar calendar) {
+            appendTo(buffer, calendar.get(mField));
+        }
+
+        public final void appendTo(StringBuffer buffer, int value) {
+            if (value < 10) {
+                buffer.append((char)(value + '0'));
+            } else if (value < 100) {
+                buffer.append((char)(value / 10 + '0'));
+                buffer.append((char)(value % 10 + '0'));
+            } else {
+                buffer.append(Integer.toString(value));
+            }
+        }
+    }
+
+    /**
+     * Inner class to output an unpadded month.
+     */
+    private static class UnpaddedMonthField implements NumberRule {
+        static final UnpaddedMonthField INSTANCE = new UnpaddedMonthField();
+        
+        UnpaddedMonthField() {
+        }
+
+        public int estimateLength() {
+            return 2;
+        }
+
+        public void appendTo(StringBuffer buffer, Calendar calendar) {
+            appendTo(buffer, calendar.get(Calendar.MONTH) + 1);
+        }
+
+        public final void appendTo(StringBuffer buffer, int value) {
+            if (value < 10) {
+                buffer.append((char)(value + '0'));
+            } else {
+                buffer.append((char)(value / 10 + '0'));
+                buffer.append((char)(value % 10 + '0'));
+            }
+        }
+    }
+
+    /**
+     * Inner class to output a padded number.
+     */
+    private static class PaddedNumberField implements NumberRule {
+        private final int mField;
+        private final int mSize;
+
+        PaddedNumberField(int field, int size) {
+            if (size < 3) {
+                // Should use UnpaddedNumberField or TwoDigitNumberField.
+                throw new IllegalArgumentException();
+            }
+            mField = field;
+            mSize = size;
+        }
+
+        public int estimateLength() {
+            return 4;
+        }
+
+        public void appendTo(StringBuffer buffer, Calendar calendar) {
+            appendTo(buffer, calendar.get(mField));
+        }
+
+        public final void appendTo(StringBuffer buffer, int value) {
+            if (value < 100) {
+                for (int i = mSize; --i >= 2; ) {
+                    buffer.append('0');
+                }
+                buffer.append((char)(value / 10 + '0'));
+                buffer.append((char)(value % 10 + '0'));
+            } else {
+                int digits;
+                if (value < 1000) {
+                    digits = 3;
+                } else {
+                    digits = (int)(Math.log(value) / LOG_10) + 1;
+                }
+                for (int i = mSize; --i >= digits; ) {
+                    buffer.append('0');
+                }
+                buffer.append(Integer.toString(value));
+            }
+        }
+    }
+
+    /**
+     * Inner class to output a two digit number.
+     */
+    private static class TwoDigitNumberField implements NumberRule {
+        private final int mField;
+
+        TwoDigitNumberField(int field) {
+            mField = field;
+        }
+
+        public int estimateLength() {
+            return 2;
+        }
+
+        public void appendTo(StringBuffer buffer, Calendar calendar) {
+            appendTo(buffer, calendar.get(mField));
+        }
+
+        public final void appendTo(StringBuffer buffer, int value) {
+            if (value < 100) {
+                buffer.append((char)(value / 10 + '0'));
+                buffer.append((char)(value % 10 + '0'));
+            } else {
+                buffer.append(Integer.toString(value));
+            }
+        }
+    }
+
+    /**
+     * Inner class to output a two digit year.
+     */
+    private static class TwoDigitYearField implements NumberRule {
+        static final TwoDigitYearField INSTANCE = new TwoDigitYearField();
+        
+        TwoDigitYearField() {
+        }
+
+        public int estimateLength() {
+            return 2;
+        }
+
+        public void appendTo(StringBuffer buffer, Calendar calendar) {
+            appendTo(buffer, calendar.get(Calendar.YEAR) % 100);
+        }
+
+        public final void appendTo(StringBuffer buffer, int value) {
+            buffer.append((char)(value / 10 + '0'));
+            buffer.append((char)(value % 10 + '0'));
+        }
+    }
+
+    /**
+     * Inner class to output a two digit month.
+     */
+    private static class TwoDigitMonthField implements NumberRule {
+        static final TwoDigitMonthField INSTANCE = new TwoDigitMonthField();
+        
+        TwoDigitMonthField() {
+        }
+
+        public int estimateLength() {
+            return 2;
+        }
+
+        public void appendTo(StringBuffer buffer, Calendar calendar) {
+            appendTo(buffer, calendar.get(Calendar.MONTH) + 1);
+        }
+
+        public final void appendTo(StringBuffer buffer, int value) {
+            buffer.append((char)(value / 10 + '0'));
+            buffer.append((char)(value % 10 + '0'));
+        }
+    }
+
+    /**
+     * Inner class to output the twelve hour field.
+     */
+    private static class TwelveHourField implements NumberRule {
+        private final NumberRule mRule;
+
+        TwelveHourField(NumberRule rule) {
+            mRule = rule;
+        }
+
+        public int estimateLength() {
+            return mRule.estimateLength();
+        }
+
+        public void appendTo(StringBuffer buffer, Calendar calendar) {
+            int value = calendar.get(Calendar.HOUR);
+            if (value == 0) {
+                value = calendar.getLeastMaximum(Calendar.HOUR) + 1;
+            }
+            mRule.appendTo(buffer, value);
+        }
+
+        public void appendTo(StringBuffer buffer, int value) {
+            mRule.appendTo(buffer, value);
+        }
+    }
+
+    /**
+     * Inner class to output the twenty four hour field.
+     */
+    private static class TwentyFourHourField implements NumberRule {
+        private final NumberRule mRule;
+
+        TwentyFourHourField(NumberRule rule) {
+            mRule = rule;
+        }
+
+        public int estimateLength() {
+            return mRule.estimateLength();
+        }
+
+        public void appendTo(StringBuffer buffer, Calendar calendar) {
+            int value = calendar.get(Calendar.HOUR_OF_DAY);
+            if (value == 0) {
+                value = calendar.getMaximum(Calendar.HOUR_OF_DAY) + 1;
+            }
+            mRule.appendTo(buffer, value);
+        }
+
+        public void appendTo(StringBuffer buffer, int value) {
+            mRule.appendTo(buffer, value);
+        }
+    }
+
+    /**
+     * Inner class to output a time zone name.
+     */
+    private static class TimeZoneNameRule implements Rule {
+        private final TimeZone mTimeZone;
+        private final boolean mTimeZoneForced;
+        private final Locale mLocale;
+        private final int mStyle;
+        private final String mStandard;
+        private final String mDaylight;
+
+        TimeZoneNameRule(TimeZone timeZone, boolean timeZoneForced, Locale locale, int style) {
+            mTimeZone = timeZone;
+            mTimeZoneForced = timeZoneForced;
+            mLocale = locale;
+            mStyle = style;
+
+            if (timeZoneForced) {
+                mStandard = getTimeZoneDisplay(timeZone, false, style, locale);
+                mDaylight = getTimeZoneDisplay(timeZone, true, style, locale);
+            } else {
+                mStandard = null;
+                mDaylight = null;
+            }
+        }
+
+        public int estimateLength() {
+            if (mTimeZoneForced) {
+                return Math.max(mStandard.length(), mDaylight.length());
+            } else if (mStyle == TimeZone.SHORT) {
+                return 4;
+            } else {
+                return 40;
+            }
+        }
+
+        public void appendTo(StringBuffer buffer, Calendar calendar) {
+            if (mTimeZoneForced) {
+                if (mTimeZone.useDaylightTime() && calendar.get(Calendar.DST_OFFSET) != 0) {
+                    buffer.append(mDaylight);
+                } else {
+                    buffer.append(mStandard);
+                }
+            } else {
+                TimeZone timeZone = calendar.getTimeZone();
+                if (timeZone.useDaylightTime() && calendar.get(Calendar.DST_OFFSET) != 0) {
+                    buffer.append(getTimeZoneDisplay(timeZone, true, mStyle, mLocale));
+                } else {
+                    buffer.append(getTimeZoneDisplay(timeZone, false, mStyle, mLocale));
+                }
+            }
+        }
+    }
+
+    /**
+     * Inner class to output a time zone as a number +/-HHMM
+     * or +/-HH:MM.
+     */
+    private static class TimeZoneNumberRule implements Rule {
+        static final TimeZoneNumberRule INSTANCE_COLON = new TimeZoneNumberRule(true);
+        static final TimeZoneNumberRule INSTANCE_NO_COLON = new TimeZoneNumberRule(false);
+        
+        final boolean mColon;
+        
+        TimeZoneNumberRule(boolean colon) {
+            mColon = colon;
+        }
+
+        public int estimateLength() {
+            return 5;
+        }
+
+        public void appendTo(StringBuffer buffer, Calendar calendar) {
+            int offset = calendar.get(Calendar.ZONE_OFFSET) + calendar.get(Calendar.DST_OFFSET);
+            
+            if (offset < 0) {
+                buffer.append('-');
+                offset = -offset;
+            } else {
+                buffer.append('+');
+            }
+            
+            int hours = offset / (60 * 60 * 1000);
+            buffer.append((char)(hours / 10 + '0'));
+            buffer.append((char)(hours % 10 + '0'));
+            
+            if (mColon) {
+                buffer.append(':');
+            }
+            
+            int minutes = offset / (60 * 1000) - 60 * hours;
+            buffer.append((char)(minutes / 10 + '0'));
+            buffer.append((char)(minutes % 10 + '0'));
+        }            
+    }
+
+    // ----------------------------------------------------------------------
+    /**
+     * Inner class that acts as a compound key for time zone names.
+     */
+    private static class TimeZoneDisplayKey {
+        private final TimeZone mTimeZone;
+        private final int mStyle;
+        private final Locale mLocale;
+
+        TimeZoneDisplayKey(TimeZone timeZone,
+                           boolean daylight, int style, Locale locale) {
+            mTimeZone = timeZone;
+            if (daylight) {
+                style |= 0x80000000;
+            }
+            mStyle = style;
+            mLocale = locale;
+        }
+
+        public int hashCode() {
+            return mStyle * 31 + mLocale.hashCode();
+        }
+
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+            if (obj instanceof TimeZoneDisplayKey) {
+                TimeZoneDisplayKey other = (TimeZoneDisplayKey)obj;
+                return
+                    mTimeZone.equals(other.mTimeZone) &&
+                    mStyle == other.mStyle &&
+                    mLocale.equals(other.mLocale);
+            }
+            return false;
+        }
+    }
+
+    // ----------------------------------------------------------------------
+    /**
+     * Helper class for creating compound objects.
+     *
+     * One use for this class is to create a hashtable key
+     * out of multiple objects.
+     */
+    private static class Pair {
+        private final Object mObj1;
+        private final Object mObj2;
+
+        public Pair(Object obj1, Object obj2) {
+            mObj1 = obj1;
+            mObj2 = obj2;
+        }
+
+        public boolean equals(Object obj) {
+            if (this == obj) {
+                return true;
+            }
+
+            if (!(obj instanceof Pair)) {
+                return false;
+            }
+
+            Pair key = (Pair)obj;
+
+            return
+                (mObj1 == null ?
+                 key.mObj1 == null : mObj1.equals(key.mObj1)) &&
+                (mObj2 == null ?
+                 key.mObj2 == null : mObj2.equals(key.mObj2));
+        }
+
+        public int hashCode() {
+            return
+                (mObj1 == null ? 0 : mObj1.hashCode()) +
+                (mObj2 == null ? 0 : mObj2.hashCode());
+        }
+
+        public String toString() {
+            return "[" + mObj1 + ':' + mObj2 + ']';
+        }
+    }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/time/StopWatch.java
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/time/StopWatch.java,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/time/StopWatch.java	30 Aug 2012 16:24:43 -0000	1.1
@@ -0,0 +1,201 @@
+/* ====================================================================
+ * The Apache Software License, Version 1.1
+ *
+ * Copyright (c) 2002-2003 The Apache Software Foundation.  All rights
+ * reserved.
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ *    notice, this list of conditions and the following disclaimer.
+ *
+ * 2. Redistributions in binary form must reproduce the above copyright
+ *    notice, this list of conditions and the following disclaimer in
+ *    the documentation and/or other materials provided with the
+ *    distribution.
+ *
+ * 3. The end-user documentation included with the redistribution, if
+ *    any, must include the following acknowledgement:
+ *       "This product includes software developed by the
+ *        Apache Software Foundation (http://www.apache.org/)."
+ *    Alternately, this acknowledgement may appear in the software itself,
+ *    if and wherever such third-party acknowledgements normally appear.
+ *
+ * 4. The names "The Jakarta Project", "Commons", and "Apache Software
+ *    Foundation" must not be used to endorse or promote products derived
+ *    from this software without prior written permission. For written
+ *    permission, please contact apache@apache.org.
+ *
+ * 5. Products derived from this software may not be called "Apache"
+ *    nor may "Apache" appear in their names without prior written
+ *    permission of the Apache Software Foundation.
+ *
+ * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
+ * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+ * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
+ * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
+ * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
+ * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
+ * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
+ * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
+ * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
+ * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
+ * SUCH DAMAGE.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation.  For more
+ * information on the Apache Software Foundation, please see
+ *  .
+ */
+package org.apache.commons.lang.time;
+
+/**
+ * StopWatch provides a convenient API for timings.
+ * 
+ * The methods do not protect against inappropriate calls. Thus you
+ * can call stop before start, resume before suspend or unsplit before split.
+ * The results are indeterminate in these cases.
+ * 
+ * To start the watch, call {@link #start()}. At this point you can:
+ * 
+ *  - {@link #split()} the watch to get the time whilst the watch continues in the
+ *   background. {@link #unsplit()} will remove the effect of the split. At this point,
+ *   these three options are available again.
 
+ *  - {@link #suspend()} the watch to pause it. {@link #resume()} allows the watch
+ *   to continue. Any time between the suspend and resume will not be counted in
+ *   the total. At this point, these three options are available again.
 
+ *  - {@link #stop()} the watch to complete the timing session.
 
+ * 
+ *
+ * It is intended that the output methods {@link #toString()} and {@link #getTime()}
+ * should only be called after stop, split or suspend, however a suitable result will
+ * be returned at other points.
+ *
+ * @author Henri Yandell
+ * @author Stephen Colebourne
+ * @since 2.0
+ * @version $Id: StopWatch.java,v 1.1 2012/08/30 16:24:43 marcin Exp $
+ */
+public class StopWatch {
+    
+    /**
+     * The start time.
+     */
+    private long startTime = -1;
+    /**
+     * The stop time.
+     */
+    private long stopTime = -1;
+
+    /**
+     * Constructor.
+     */
+    public StopWatch() {
+    }
+
+    /**
+     * Start the stopwatch.
+     * 
+     * This method starts a new timing session, clearing any previous values.
+     */
+    public void start() {
+        stopTime = -1;
+        startTime = System.currentTimeMillis();
+    }
+
+    /**
+     * Stop the stopwatch.
+     * 
+     * This method ends a new timing session, allowing the time to be retrieved.
+     */
+    public void stop() {
+        stopTime = System.currentTimeMillis();
+    }
+
+    /**
+     * Reset the stopwatch.
+     * 
+     * This method clears the internal values to allow the object to be reused.
+     */
+    public void reset() {
+        startTime = -1;
+        stopTime = -1;
+    }
+
+    /**
+     * Split the time.
+     * 
+     * This method sets the stop time of the watch to allow a time to be extracted.
+     * The start time is unaffected, enabling {@link #unsplit()} to contine the 
+     * timing from the original start point.
+     */
+    public void split() {
+        stopTime = System.currentTimeMillis();
+    }
+
+    /**
+     * Remove a split.
+     * 
+     * This method clears the stop time. The start time is unaffected, enabling 
+     * timing from the original start point to continue.
+     */
+    public void unsplit() {
+        stopTime = -1;
+    }
+
+    /**
+     * Suspend the stopwatch for later resumption.
+     * 
+     * This method suspends the watch until it is resumed. The watch will not include
+     * time between the suspend and resume calls in the total time.
+     */
+    public void suspend() {
+        stopTime = System.currentTimeMillis();
+    }
+
+    /**
+     * Resume the stopwatch after a suspend.
+     * 
+     * This method resumes the watch after it was suspended. The watch will not include
+     * time between the suspend and resume calls in the total time.
+     */
+    public void resume() {
+        startTime += (System.currentTimeMillis() - stopTime);
+        stopTime = -1;
+    }
+
+    /**
+     * Get the time on the stopwatch.
+     * 
+     * This is either the time between start and latest split, between start
+     * and stop, or the time between the start and the moment this method is called.
+     * 
+     * @return the time in milliseconds
+     */
+    public long getTime() {
+        if (stopTime == -1) {
+            if (startTime == -1) {
+                return 0;
+            }
+            return (System.currentTimeMillis() - this.startTime);
+        }
+        return (this.stopTime - this.startTime);
+    }
+
+    /**
+     * Gets a summary of the time that the stopwatch recorded as a string.
+     * 
+     * The format used is ISO8601-like,
+     * hours:minutes:seconds.milliseconds.
+     * 
+     * @return the time as a String
+     */
+    public String toString() {
+        return DurationFormatUtils.formatISO(getTime());
+    }
+
+}
Index: 3rdParty_sources/commons-lang/org/apache/commons/lang/time/package.html
===================================================================
RCS file: /usr/local/cvsroot/3rdParty_sources/commons-lang/org/apache/commons/lang/time/package.html,v
diff -u
--- /dev/null	1 Jan 1970 00:00:00 -0000
+++ 3rdParty_sources/commons-lang/org/apache/commons/lang/time/package.html	30 Aug 2012 16:24:43 -0000	1.1
@@ -0,0 +1,15 @@
+
+
+
+Provides classes and methods to work with dates and durations.
+
+This includes:
+
+DateUtils - a set of static utility methods for working with dates
+FastDateFormat - a replacement for SimpleDateFormat that is fast and thread-safe
+DateFormatUtils - a formatting class for dates
+StopWatch - a duration timer
+
+@since 2.0
+
+
Index: lams_build/3rdParty.userlibraries
===================================================================
RCS file: /usr/local/cvsroot/lams_build/3rdParty.userlibraries,v
diff -u -r1.56 -r1.57
--- lams_build/3rdParty.userlibraries	22 Aug 2012 17:28:46 -0000	1.56
+++ lams_build/3rdParty.userlibraries	30 Aug 2012 16:24:27 -0000	1.57
@@ -26,7 +26,7 @@
          
          
          
-         
+