You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@directory.apache.org by tr...@apache.org on 2006/01/20 14:48:55 UTC

svn commit: r370807 [7/22] - in /directory/sandbox/trustin/mina-spi: ./ core/src/main/java/org/apache/mina/common/ core/src/main/java/org/apache/mina/common/support/ core/src/main/java/org/apache/mina/common/support/discovery/ core/src/main/java/org/ap...

Added: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/CharUtils.java
URL: http://svn.apache.org/viewcvs/directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/CharUtils.java?rev=370807&view=auto
==============================================================================
--- directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/CharUtils.java (added)
+++ directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/CharUtils.java Fri Jan 20 05:47:50 2006
@@ -0,0 +1,542 @@
+/*
+ * Copyright 2004-2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.mina.common.support.lang;
+
+/**
+ * <p>Operations on char primitives and Character objects.</p>
+ *
+ * <p>This class tries to handle <code>null</code> input gracefully.
+ * An exception will not be thrown for a <code>null</code> input.
+ * Each method documents its behaviour in more detail.</p>
+ * 
+ * @author Stephen Colebourne
+ * @since 2.1
+ * @version $Id$
+ */
+public class CharUtils {
+    
+    private static final String CHAR_STRING = 
+        "\u0000\u0001\u0002\u0003\u0004\u0005\u0006\u0007" +
+        "\b\t\n\u000b\f\r\u000e\u000f" +
+        "\u0010\u0011\u0012\u0013\u0014\u0015\u0016\u0017" +
+        "\u0018\u0019\u001a\u001b\u001c\u001d\u001e\u001f" +
+        "\u0020\u0021\"\u0023\u0024\u0025\u0026\u0027" +
+        "\u0028\u0029\u002a\u002b\u002c\u002d\u002e\u002f" +
+        "\u0030\u0031\u0032\u0033\u0034\u0035\u0036\u0037" +
+        "\u0038\u0039\u003a\u003b\u003c\u003d\u003e\u003f" +
+        "\u0040\u0041\u0042\u0043\u0044\u0045\u0046\u0047" +
+        "\u0048\u0049\u004a\u004b\u004c\u004d\u004e\u004f" +
+        "\u0050\u0051\u0052\u0053\u0054\u0055\u0056\u0057" +
+        "\u0058\u0059\u005a\u005b\\\u005d\u005e\u005f" +
+        "\u0060\u0061\u0062\u0063\u0064\u0065\u0066\u0067" +
+        "\u0068\u0069\u006a\u006b\u006c\u006d\u006e\u006f" +
+        "\u0070\u0071\u0072\u0073\u0074\u0075\u0076\u0077" +
+        "\u0078\u0079\u007a\u007b\u007c\u007d\u007e\u007f";
+    
+    private static final String[] CHAR_STRING_ARRAY = new String[128];
+    private static final Character[] CHAR_ARRAY = new Character[128];
+    
+    static {
+        for (int i = 127; i >= 0; i--) {
+            CHAR_STRING_ARRAY[i] = CHAR_STRING.substring(i, i + 1);
+            CHAR_ARRAY[i] = new Character((char) i);
+        }
+    }
+    
+    /**
+     * <p><code>CharUtils</code> instances should NOT be constructed in standard programming.
+     * Instead, the class should be used as <code>CharUtils.toString('c');</code>.</p>
+     *
+     * <p>This constructor is public to permit tools that require a JavaBean instance
+     * to operate.</p>
+     */
+    public CharUtils() {
+    }
+
+    //-----------------------------------------------------------------------
+    /**
+     * <p>Converts the character to a Character.</p>
+     * 
+     * <p>For ASCII 7 bit characters, this uses a cache that will return the
+     * same Character object each time.</p>
+     *
+     * <pre>
+     *   CharUtils.toCharacterObject(' ')  = ' '
+     *   CharUtils.toCharacterObject('A')  = 'A'
+     * </pre>
+     *
+     * @param ch  the character to convert
+     * @return a Character of the specified character
+     */
+    public static Character toCharacterObject(char ch) {
+        if (ch < CHAR_ARRAY.length) {
+            return CHAR_ARRAY[ch];
+        } else {
+            return new Character(ch);
+        }
+    }
+    
+    /**
+     * <p>Converts the String to a Character using the first character, returning
+     * null for empty Strings.</p>
+     * 
+     * <p>For ASCII 7 bit characters, this uses a cache that will return the
+     * same Character object each time.</p>
+     * 
+     * <pre>
+     *   CharUtils.toCharacterObject(null) = null
+     *   CharUtils.toCharacterObject("")   = null
+     *   CharUtils.toCharacterObject("A")  = 'A'
+     *   CharUtils.toCharacterObject("BA") = 'B'
+     * </pre>
+     *
+     * @param str  the character to convert
+     * @return the Character value of the first letter of the String
+     */
+    public static Character toCharacterObject(String str) {
+        if (StringUtils.isEmpty(str)) {
+            return null;
+        }
+        return toCharacterObject(str.charAt(0));
+    }
+    
+    //-----------------------------------------------------------------------
+    /**
+     * <p>Converts the Character to a char throwing an exception for <code>null</code>.</p>
+     * 
+     * <pre>
+     *   CharUtils.toChar(null) = IllegalArgumentException
+     *   CharUtils.toChar(' ')  = ' '
+     *   CharUtils.toChar('A')  = 'A'
+     * </pre>
+     *
+     * @param ch  the character to convert
+     * @return the char value of the Character
+     * @throws IllegalArgumentException if the Character is null
+     */
+    public static char toChar(Character ch) {
+        if (ch == null) {
+            throw new IllegalArgumentException("The Character must not be null");
+        }
+        return ch.charValue();
+    }
+    
+    /**
+     * <p>Converts the Character to a char handling <code>null</code>.</p>
+     * 
+     * <pre>
+     *   CharUtils.toChar(null, 'X') = 'X'
+     *   CharUtils.toChar(' ', 'X')  = ' '
+     *   CharUtils.toChar('A', 'X')  = 'A'
+     * </pre>
+     *
+     * @param ch  the character to convert
+     * @param defaultValue  the value to use if the  Character is null
+     * @return the char value of the Character or the default if null
+     */
+    public static char toChar(Character ch, char defaultValue) {
+        if (ch == null) {
+            return defaultValue;
+        }
+        return ch.charValue();
+    }
+    
+    //-----------------------------------------------------------------------
+    /**
+     * <p>Converts the String to a char using the first character, throwing
+     * an exception on empty Strings.</p>
+     * 
+     * <pre>
+     *   CharUtils.toChar(null) = IllegalArgumentException
+     *   CharUtils.toChar("")   = IllegalArgumentException
+     *   CharUtils.toChar("A")  = 'A'
+     *   CharUtils.toChar("BA") = 'B'
+     * </pre>
+     *
+     * @param str  the character to convert
+     * @return the char value of the first letter of the String
+     * @throws IllegalArgumentException if the String is empty
+     */
+    public static char toChar(String str) {
+        if (StringUtils.isEmpty(str)) {
+            throw new IllegalArgumentException("The String must not be empty");
+        }
+        return str.charAt(0);
+    }
+    
+    /**
+     * <p>Converts the String to a char using the first character, defaulting
+     * the value on empty Strings.</p>
+     * 
+     * <pre>
+     *   CharUtils.toChar(null, 'X') = 'X'
+     *   CharUtils.toChar("", 'X')   = 'X'
+     *   CharUtils.toChar("A", 'X')  = 'A'
+     *   CharUtils.toChar("BA", 'X') = 'B'
+     * </pre>
+     *
+     * @param str  the character to convert
+     * @param defaultValue  the value to use if the  Character is null
+     * @return the char value of the first letter of the String or the default if null
+     */
+    public static char toChar(String str, char defaultValue) {
+        if (StringUtils.isEmpty(str)) {
+            return defaultValue;
+        }
+        return str.charAt(0);
+    }
+    
+    //-----------------------------------------------------------------------
+    /**
+     * <p>Converts the character to the Integer it represents, throwing an
+     * exception if the character is not numeric.</p>
+     * 
+     * <p>This method coverts the char '1' to the int 1 and so on.</p>
+     *
+     * <pre>
+     *   CharUtils.toIntValue('3')  = 3
+     *   CharUtils.toIntValue('A')  = IllegalArgumentException
+     * </pre>
+     *
+     * @param ch  the character to convert
+     * @return the int value of the character
+     * @throws IllegalArgumentException if the character is not ASCII numeric
+     */
+    public static int toIntValue(char ch) {
+        if (isAsciiNumeric(ch) == false) {
+            throw new IllegalArgumentException("The character " + ch + " is not in the range '0' - '9'");
+        }
+        return ch - 48;
+    }
+    
+    /**
+     * <p>Converts the character to the Integer it represents, throwing an
+     * exception if the character is not numeric.</p>
+     * 
+     * <p>This method coverts the char '1' to the int 1 and so on.</p>
+     *
+     * <pre>
+     *   CharUtils.toIntValue('3', -1)  = 3
+     *   CharUtils.toIntValue('A', -1)  = -1
+     * </pre>
+     *
+     * @param ch  the character to convert
+     * @param defaultValue  the default value to use if the character is not numeric
+     * @return the int value of the character
+     */
+    public static int toIntValue(char ch, int defaultValue) {
+        if (isAsciiNumeric(ch) == false) {
+            return defaultValue;
+        }
+        return ch - 48;
+    }
+    
+    /**
+     * <p>Converts the character to the Integer it represents, throwing an
+     * exception if the character is not numeric.</p>
+     * 
+     * <p>This method coverts the char '1' to the int 1 and so on.</p>
+     *
+     * <pre>
+     *   CharUtils.toIntValue(null) = IllegalArgumentException
+     *   CharUtils.toIntValue('3')  = 3
+     *   CharUtils.toIntValue('A')  = IllegalArgumentException
+     * </pre>
+     *
+     * @param ch  the character to convert, not null
+     * @return the int value of the character
+     * @throws IllegalArgumentException if the Character is not ASCII numeric or is null
+     */
+    public static int toIntValue(Character ch) {
+        if (ch == null) {
+            throw new IllegalArgumentException("The character must not be null");
+        }
+        return toIntValue(ch.charValue());
+    }
+    
+    /**
+     * <p>Converts the character to the Integer it represents, throwing an
+     * exception if the character is not numeric.</p>
+     * 
+     * <p>This method coverts the char '1' to the int 1 and so on.</p>
+     *
+     * <pre>
+     *   CharUtils.toIntValue(null, -1) = -1
+     *   CharUtils.toIntValue('3', -1)  = 3
+     *   CharUtils.toIntValue('A', -1)  = -1
+     * </pre>
+     *
+     * @param ch  the character to convert
+     * @param defaultValue  the default value to use if the character is not numeric
+     * @return the int value of the character
+     */
+    public static int toIntValue(Character ch, int defaultValue) {
+        if (ch == null) {
+            return defaultValue;
+        }
+        return toIntValue(ch.charValue(), defaultValue);
+    }
+    
+    //-----------------------------------------------------------------------
+    /**
+     * <p>Converts the character to a String that contains the one character.</p>
+     * 
+     * <p>For ASCII 7 bit characters, this uses a cache that will return the
+     * same String object each time.</p>
+     *
+     * <pre>
+     *   CharUtils.toString(' ')  = " "
+     *   CharUtils.toString('A')  = "A"
+     * </pre>
+     *
+     * @param ch  the character to convert
+     * @return a String containing the one specified character
+     */
+    public static String toString(char ch) {
+        if (ch < 128) {
+            return CHAR_STRING_ARRAY[ch];
+        } else {
+            return new String(new char[] {ch});
+        }
+    }
+    
+    /**
+     * <p>Converts the character to a String that contains the one character.</p>
+     * 
+     * <p>For ASCII 7 bit characters, this uses a cache that will return the
+     * same String object each time.</p>
+     * 
+     * <p>If <code>null</code> is passed in, <code>null</code> will be returned.</p>
+     *
+     * <pre>
+     *   CharUtils.toString(null) = null
+     *   CharUtils.toString(' ')  = " "
+     *   CharUtils.toString('A')  = "A"
+     * </pre>
+     *
+     * @param ch  the character to convert
+     * @return a String containing the one specified character
+     */
+    public static String toString(Character ch) {
+        if (ch == null) {
+            return null;
+        } else {
+            return toString(ch.charValue());
+        }
+    }
+    
+    //--------------------------------------------------------------------------
+    /**
+     * <p>Converts the string to the unicode format '\u0020'.</p>
+     * 
+     * <p>This format is the Java source code format.</p>
+     *
+     * <pre>
+     *   CharUtils.unicodeEscaped(' ') = "\u0020"
+     *   CharUtils.unicodeEscaped('A') = "\u0041"
+     * </pre>
+     * 
+     * @param ch  the character to convert
+     * @return the escaped unicode string
+     */
+    public static String unicodeEscaped(char ch) {
+        if (ch < 0x10) {
+            return "\\u000" + Integer.toHexString(ch);
+        } else if (ch < 0x100) {
+            return "\\u00" + Integer.toHexString(ch);
+        } else if (ch < 0x1000) {
+            return "\\u0" + Integer.toHexString(ch);
+        }
+        return "\\u" + Integer.toHexString(ch);
+    }
+    
+    /**
+     * <p>Converts the string to the unicode format '\u0020'.</p>
+     * 
+     * <p>This format is the Java source code format.</p>
+     * 
+     * <p>If <code>null</code> is passed in, <code>null</code> will be returned.</p>
+     *
+     * <pre>
+     *   CharUtils.unicodeEscaped(null) = null
+     *   CharUtils.unicodeEscaped(' ')  = "\u0020"
+     *   CharUtils.unicodeEscaped('A')  = "\u0041"
+     * </pre>
+     * 
+     * @param ch  the character to convert, may be null
+     * @return the escaped unicode string, null if null input
+     */
+    public static String unicodeEscaped(Character ch) {
+        if (ch == null) {
+            return null;
+        }
+        return unicodeEscaped(ch.charValue());
+    }
+    
+    //--------------------------------------------------------------------------
+    /**
+     * <p>Checks whether the character is ASCII 7 bit.</p>
+     *
+     * <pre>
+     *   CharUtils.isAscii('a')  = true
+     *   CharUtils.isAscii('A')  = true
+     *   CharUtils.isAscii('3')  = true
+     *   CharUtils.isAscii('-')  = true
+     *   CharUtils.isAscii('\n') = true
+     *   CharUtils.isAscii('&copy;') = false
+     * </pre>
+     * 
+     * @param ch  the character to check
+     * @return true if less than 128
+     */
+    public static boolean isAscii(char ch) {
+        return ch < 128;
+    }
+    
+    /**
+     * <p>Checks whether the character is ASCII 7 bit printable.</p>
+     *
+     * <pre>
+     *   CharUtils.isAsciiPrintable('a')  = true
+     *   CharUtils.isAsciiPrintable('A')  = true
+     *   CharUtils.isAsciiPrintable('3')  = true
+     *   CharUtils.isAsciiPrintable('-')  = true
+     *   CharUtils.isAsciiPrintable('\n') = false
+     *   CharUtils.isAsciiPrintable('&copy;') = false
+     * </pre>
+     * 
+     * @param ch  the character to check
+     * @return true if between 32 and 126 inclusive
+     */
+    public static boolean isAsciiPrintable(char ch) {
+        return ch >= 32 && ch < 127;
+    }
+    
+    /**
+     * <p>Checks whether the character is ASCII 7 bit control.</p>
+     *
+     * <pre>
+     *   CharUtils.isAsciiControl('a')  = false
+     *   CharUtils.isAsciiControl('A')  = false
+     *   CharUtils.isAsciiControl('3')  = false
+     *   CharUtils.isAsciiControl('-')  = false
+     *   CharUtils.isAsciiControl('\n') = true
+     *   CharUtils.isAsciiControl('&copy;') = false
+     * </pre>
+     * 
+     * @param ch  the character to check
+     * @return true if less than 32 or equals 127
+     */
+    public static boolean isAsciiControl(char ch) {
+        return ch < 32 || ch == 127;
+    }
+    
+    /**
+     * <p>Checks whether the character is ASCII 7 bit alphabetic.</p>
+     *
+     * <pre>
+     *   CharUtils.isAsciiAlpha('a')  = true
+     *   CharUtils.isAsciiAlpha('A')  = true
+     *   CharUtils.isAsciiAlpha('3')  = false
+     *   CharUtils.isAsciiAlpha('-')  = false
+     *   CharUtils.isAsciiAlpha('\n') = false
+     *   CharUtils.isAsciiAlpha('&copy;') = false
+     * </pre>
+     * 
+     * @param ch  the character to check
+     * @return true if between 65 and 90 or 97 and 122 inclusive
+     */
+    public static boolean isAsciiAlpha(char ch) {
+        return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z');
+    }
+    
+    /**
+     * <p>Checks whether the character is ASCII 7 bit alphabetic upper case.</p>
+     *
+     * <pre>
+     *   CharUtils.isAsciiAlphaUpper('a')  = false
+     *   CharUtils.isAsciiAlphaUpper('A')  = true
+     *   CharUtils.isAsciiAlphaUpper('3')  = false
+     *   CharUtils.isAsciiAlphaUpper('-')  = false
+     *   CharUtils.isAsciiAlphaUpper('\n') = false
+     *   CharUtils.isAsciiAlphaUpper('&copy;') = false
+     * </pre>
+     * 
+     * @param ch  the character to check
+     * @return true if between 65 and 90 inclusive
+     */
+    public static boolean isAsciiAlphaUpper(char ch) {
+        return ch >= 'A' && ch <= 'Z';
+    }
+    
+    /**
+     * <p>Checks whether the character is ASCII 7 bit alphabetic lower case.</p>
+     *
+     * <pre>
+     *   CharUtils.isAsciiAlphaLower('a')  = true
+     *   CharUtils.isAsciiAlphaLower('A')  = false
+     *   CharUtils.isAsciiAlphaLower('3')  = false
+     *   CharUtils.isAsciiAlphaLower('-')  = false
+     *   CharUtils.isAsciiAlphaLower('\n') = false
+     *   CharUtils.isAsciiAlphaLower('&copy;') = false
+     * </pre>
+     * 
+     * @param ch  the character to check
+     * @return true if between 97 and 122 inclusive
+     */
+    public static boolean isAsciiAlphaLower(char ch) {
+        return ch >= 'a' && ch <= 'z';
+    }
+    
+    /**
+     * <p>Checks whether the character is ASCII 7 bit numeric.</p>
+     *
+     * <pre>
+     *   CharUtils.isAsciiNumeric('a')  = false
+     *   CharUtils.isAsciiNumeric('A')  = false
+     *   CharUtils.isAsciiNumeric('3')  = true
+     *   CharUtils.isAsciiNumeric('-')  = false
+     *   CharUtils.isAsciiNumeric('\n') = false
+     *   CharUtils.isAsciiNumeric('&copy;') = false
+     * </pre>
+     * 
+     * @param ch  the character to check
+     * @return true if between 48 and 57 inclusive
+     */
+    public static boolean isAsciiNumeric(char ch) {
+        return ch >= '0' && ch <= '9';
+    }
+    
+    /**
+     * <p>Checks whether the character is ASCII 7 bit numeric.</p>
+     *
+     * <pre>
+     *   CharUtils.isAsciiAlphanumeric('a')  = true
+     *   CharUtils.isAsciiAlphanumeric('A')  = true
+     *   CharUtils.isAsciiAlphanumeric('3')  = true
+     *   CharUtils.isAsciiAlphanumeric('-')  = false
+     *   CharUtils.isAsciiAlphanumeric('\n') = false
+     *   CharUtils.isAsciiAlphanumeric('&copy;') = false
+     * </pre>
+     * 
+     * @param ch  the character to check
+     * @return true if between 48 and 57 or 65 and 90 or 97 and 122 inclusive
+     */
+    public static boolean isAsciiAlphanumeric(char ch) {
+        return (ch >= 'A' && ch <= 'Z') || (ch >= 'a' && ch <= 'z') || (ch >= '0' && ch <= '9');
+    }
+    
+}

Propchange: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/CharUtils.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/ClassUtils.java
URL: http://svn.apache.org/viewcvs/directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/ClassUtils.java?rev=370807&view=auto
==============================================================================
--- directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/ClassUtils.java (added)
+++ directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/ClassUtils.java Fri Jan 20 05:47:50 2006
@@ -0,0 +1,500 @@
+/*
+ * Copyright 2002-2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.mina.common.support.lang;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Map;
+
+/**
+ * <p>Operates on classes without using reflection.</p>
+ *
+ * <p>This class handles invalid <code>null</code> inputs as best it can.
+ * Each method documents its behaviour in more detail.</p>
+ *
+ * @author Stephen Colebourne
+ * @author Gary Gregory
+ * @author Norm Deane
+ * @since 2.0
+ * @version $Id$
+ */
+public class ClassUtils {
+
+    /**
+     * <p>The package separator character: <code>'&#x2e;' == {@value}</code>.</p>
+     */
+    public static final char PACKAGE_SEPARATOR_CHAR = '.';
+    
+    /**
+     * <p>The package separator String: <code>"&#x2e;"</code>.</p>
+     */
+    public static final String PACKAGE_SEPARATOR = String.valueOf(PACKAGE_SEPARATOR_CHAR);
+    
+    /**
+     * <p>The inner class separator character: <code>'$' == {@value}</code>.</p>
+     */
+    public static final char INNER_CLASS_SEPARATOR_CHAR = '$';
+    
+    /**
+     * <p>The inner class separator String: <code>"$"</code>.</p>
+     */
+    public static final String INNER_CLASS_SEPARATOR = String.valueOf(INNER_CLASS_SEPARATOR_CHAR);
+    
+    /** 
+     * Maps primitive <code>Class</code>es to their corresponding wrapper <code>Class</code>. 
+     */
+    private static Map  primitiveWrapperMap = new HashMap();
+    static {
+         primitiveWrapperMap.put(Boolean.TYPE, Boolean.class);
+         primitiveWrapperMap.put(Byte.TYPE, Byte.class);
+         primitiveWrapperMap.put(Character.TYPE, Character.class);
+         primitiveWrapperMap.put(Short.TYPE, Short.class);
+         primitiveWrapperMap.put(Integer.TYPE, Integer.class);
+         primitiveWrapperMap.put(Long.TYPE, Long.class);
+         primitiveWrapperMap.put(Double.TYPE, Double.class);
+         primitiveWrapperMap.put(Float.TYPE, Float.class);
+    }
+    
+    /**
+     * <p>ClassUtils instances should NOT be constructed in standard programming.
+     * Instead, the class should be used as
+     * <code>ClassUtils.getShortClassName(cls)</code>.</p>
+     *
+     * <p>This constructor is public to permit tools that require a JavaBean
+     * instance to operate.</p>
+     */
+    public ClassUtils() {
+    }
+
+    // Short class name
+    // ----------------------------------------------------------------------
+    /**
+     * <p>Gets the class name minus the package name for an <code>Object</code>.</p>
+     * 
+     * @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());
+    }
+    
+    /**
+     * <p>Gets the class name minus the package name from a <code>Class</code>.</p>
+     * 
+     * @param cls  the class to get the short name for.
+     * @return the class name without the package name or an empty string
+     */
+    public static String getShortClassName(Class cls) {
+        if (cls == null) {
+            return StringUtils.EMPTY;
+        }
+        return getShortClassName(cls.getName());
+    }
+    
+    /**
+     * <p>Gets the class name minus the package name from a String.</p>
+     *
+     * <p>The string passed in is assumed to be a class name - it is not checked.</p>
+     * 
+     * @param className  the className to get the short name for
+     * @return the class name of the class without the package name or an empty string
+     */
+    public static String getShortClassName(String className) {
+        if (className == null) {
+            return StringUtils.EMPTY;
+        }
+        if (className.length() == 0) {
+            return StringUtils.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
+    // ----------------------------------------------------------------------
+    /**
+     * <p>Gets the package name of an <code>Object</code>.</p>
+     * 
+     * @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());
+    }
+    
+    /**
+     * <p>Gets the package name of a <code>Class</code>.</p>
+     * 
+     * @param cls  the class to get the package name for, may be <code>null</code>.
+     * @return the package name or an empty string
+     */
+    public static String getPackageName(Class cls) {
+        if (cls == null) {
+            return StringUtils.EMPTY;
+        }
+        return getPackageName(cls.getName());
+    }
+    
+    /**
+     * <p>Gets the package name from a <code>String</code>.</p>
+     *
+     * <p>The string passed in is assumed to be a class name - it is not checked.</p>
+     * <p>If the class is unpackaged, return an empty string.</p>
+     * 
+     * @param className  the className to get the package name for, may be <code>null</code>
+     * @return the package name or an empty string
+     */
+    public static String getPackageName(String className) {
+        if (className == null) {
+            return StringUtils.EMPTY;
+        }
+        int i = className.lastIndexOf(PACKAGE_SEPARATOR_CHAR);
+        if (i == -1) {
+            return StringUtils.EMPTY;
+        }
+        return className.substring(0, i);
+    }
+    
+    // Superclasses/Superinterfaces
+    // ----------------------------------------------------------------------
+    /**
+     * <p>Gets a <code>List</code> of superclasses for the given class.</p>
+     * 
+     * @param cls  the class to look up, may be <code>null</code>
+     * @return the <code>List</code> of superclasses in order going up from this one
+     *  <code>null</code> 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;
+    }
+    
+    /**
+     * <p>Gets a <code>List</code> of all interfaces implemented by the given
+     * class and its superclasses.</p>
+     *
+     * <p>The order is determined by looking through each interface in turn as
+     * declared in the source file and following its hierarchy up. Then each 
+     * superclass is considered in the same way. Later duplicates are ignored, 
+     * so the order is maintained.</p>
+     * 
+     * @param cls  the class to look up, may be <code>null</code>
+     * @return the <code>List</code> of interfaces in order,
+     *  <code>null</code> 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;
+    }
+    
+    // Convert list
+    // ----------------------------------------------------------------------
+    /**
+     * <p>Given a <code>List</code> of class names, this method converts them into classes.</p>
+     *
+     * <p>A new <code>List</code> is returned. If the class name cannot be found, <code>null</code>
+     * is stored in the <code>List</code>. If the class name in the <code>List</code> is
+     * <code>null</code>, <code>null</code> is stored in the output <code>List</code>.</p>
+     * 
+     * @param classNames  the classNames to change
+     * @return a <code>List</code> of Class objects corresponding to the class names,
+     *  <code>null</code> 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;
+    }
+    
+    /**
+     * <p>Given a <code>List</code> of <code>Class</code> objects, this method converts
+     * them into class names.</p>
+     *
+     * <p>A new <code>List</code> is returned. <code>null</code> objects will be copied into
+     * the returned list as <code>null</code>.</p>
+     * 
+     * @param classes  the classes to change
+     * @return a <code>List</code> of class names corresponding to the Class objects,
+     *  <code>null</code> if null input
+     * @throws ClassCastException if <code>classes</code> contains a non-<code>Class</code> 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
+    // ----------------------------------------------------------------------
+    /**
+     * <p>Checks if an array of Classes can be assigned to another array of Classes.</p>
+     *
+     * <p>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 compatible with a set of method parameter types
+     * (the second parameter).</p>
+     *
+     * <p>Unlike the {@link Class#isAssignableFrom(java.lang.Class)} method, this
+     * method takes into account widenings of primitive classes and
+     * <code>null</code>s.</p>
+     *
+     * <p>Primitive widenings allow an int to be assigned to a <code>long</code>,
+     * <code>float</code> or <code>double</code>. This method returns the correct
+     * result for these cases.</p>
+     *
+     * <p><code>Null</code> may be assigned to any reference type. This method will
+     * return <code>true</code> if <code>null</code> is passed in and the toClass is
+     * non-primitive.</p>
+     *
+     * <p>Specifically, this method tests whether the type represented by the
+     * specified <code>Class</code> parameter can be converted to the type
+     * represented by this <code>Class</code> object via an identity conversion
+     * widening primitive or widening reference conversion. See 
+     * <em><a href="http://java.sun.com/docs/books/jls/">The Java Language Specification</a></em>,
+     * sections 5.1.1, 5.1.2 and 5.1.4 for details.</p>
+     *
+     * @param classArray  the array of Classes to check, may be <code>null</code>
+     * @param toClassArray  the array of Classes to try to assign into, may be <code>null</code>
+     * @return <code>true</code> 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;
+    }
+    
+    /**
+     * <p>Checks if one <code>Class</code> can be assigned to a variable of
+     * another <code>Class</code>.</p>
+     *
+     * <p>Unlike the {@link Class#isAssignableFrom(java.lang.Class)} method,
+     * this method takes into account widenings of primitive classes and
+     * <code>null</code>s.</p>
+     *
+     * <p>Primitive widenings allow an int to be assigned to a long, float or
+     * double. This method returns the correct result for these cases.</p>
+     *
+     * <p><code>Null</code> may be assigned to any reference type. This method
+     * will return <code>true</code> if <code>null</code> is passed in and the
+     * toClass is non-primitive.</p>
+     *
+     * <p>Specifically, this method tests whether the type represented by the
+     * specified <code>Class</code> parameter can be converted to the type
+     * represented by this <code>Class</code> object via an identity conversion
+     * widening primitive or widening reference conversion. See 
+     * <em><a href="http://java.sun.com/docs/books/jls/">The Java Language Specification</a></em>,
+     * sections 5.1.1, 5.1.2 and 5.1.4 for details.</p>
+     *
+     * @param cls  the Class to check, may be null
+     * @param toClass  the Class to try to assign into, returns false if null
+     * @return <code>true</code> 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);
+    }
+    
+    /**
+     * <p>Converts the specified primitive Class object to its corresponding
+     * wrapper Class object.</p>
+     *
+     * @param cls  the class to convert, may be null
+     * @return the wrapper class for <code>cls</code> or <code>cls</code> if
+     * <code>cls</code> is not a primitive. <code>null</code> if null input.
+     * @since 2.1
+     */
+    public static Class primitiveToWrapper(Class cls) {
+        Class convertedClass = cls;
+        if (cls != null && cls.isPrimitive()) {
+            convertedClass = (Class) primitiveWrapperMap.get(cls);
+        }   
+        return convertedClass;
+    }
+
+    /**
+     * <p>Converts the specified array of primitive Class objects to an array of 
+     * its corresponding wrapper Class objects.</p>
+     *
+     * @param classes  the class array to convert, may be null or empty
+     * @return an array which contains for each given class, the wrapper class or 
+     * the original class if class is not a primitive. <code>null</code> if null input. 
+     * Empty array if an empty array passed in.
+     * @since 2.1
+     */
+    public static Class[] primitivesToWrappers(Class[] classes) {
+        if (classes == null) {
+            return null;
+        }
+        
+        if (classes.length == 0) {
+            return classes;
+        }
+        
+        Class[] convertedClasses = new Class[classes.length];
+        for (int i=0; i < classes.length; i++) {
+            convertedClasses[i] = primitiveToWrapper( classes[i] );
+        }
+        return convertedClasses;
+    }
+
+    // Inner class
+    // ----------------------------------------------------------------------
+    /**
+     * <p>Is the specified class an inner class or static nested class.</p>
+     * 
+     * @param cls  the class to check, may be null
+     * @return <code>true</code> if the class is an inner or static nested class,
+     *  false if not or <code>null</code>
+     */
+    public static boolean isInnerClass(Class cls) {
+        if (cls == null) {
+            return false;
+        }
+        return cls.getName().indexOf(INNER_CLASS_SEPARATOR_CHAR) >= 0;
+    }
+
+}

Propchange: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/ClassUtils.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/Entities.java
URL: http://svn.apache.org/viewcvs/directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/Entities.java?rev=370807&view=auto
==============================================================================
--- directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/Entities.java (added)
+++ directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/Entities.java Fri Jan 20 05:47:50 2006
@@ -0,0 +1,686 @@
+/*
+ * Copyright 2002-2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.mina.common.support.lang;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.TreeMap;
+
+/**
+ * <p>Provides HTML and XML entity utilities.</p>
+ *
+ * @see <a href="http://hotwired.lycos.com/webmonkey/reference/special_characters/">ISO Entities</a>
+ * @see <br/><a href="http://www.w3.org/TR/REC-html32#latin1">HTML 3.2 Character Entities for ISO Latin-1</a>
+ * @see <br/><a href="http://www.w3.org/TR/REC-html40/sgml/entities.html">HTML 4.0 Character entity references</a>
+ * @see <br/><a href="http://www.w3.org/TR/html401/charset.html#h-5.3">HTML 4.01 Character References</a>
+ * @see <br/><a href="http://www.w3.org/TR/html401/charset.html#code-position">HTML 4.01 Code positions</a>
+ *
+ * @author <a href="mailto:alex@purpletech.com">Alexander Day Chaffee</a>
+ * @author <a href="mailto:ggregory@seagullsw.com">Gary Gregory</a>
+ * @since 2.0
+ * @version $Id$
+ */
+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 = {
+// <!-- Latin Extended-B -->
+        {"fnof", "402"}, //latin small f with hook = function= florin, U+0192 ISOtech -->
+// <!-- Greek -->
+        {"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 -->
+// <!-- there is no Sigmaf, and no U+03A2 character either -->
+        {"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 -->
+// <!-- General Punctuation -->
+        {"bull", "8226"}, //bullet = black small circle,U+2022 ISOpub  -->
+// <!-- bullet is NOT the same as bullet operator, U+2219 -->
+        {"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 -->
+// <!-- Letterlike Symbols -->
+        {"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 -->
+// <!-- alef symbol is NOT the same as hebrew letter alef,U+05D0 although the same glyph could be used to depict both characters -->
+// <!-- Arrows -->
+        {"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 -->
+// <!-- ISO 10646 does not say that lArr is the same as the 'is implied by' arrowbut also does not have any other character for that function. So ? lArr canbe used for 'is implied by' as ISOtech suggests -->
+        {"uArr", "8657"}, //upwards double arrow, U+21D1 ISOamsa -->
+        {"rArr", "8658"}, //rightwards double arrow,U+21D2 ISOtech -->
+// <!-- ISO 10646 does not say this is the 'implies' character but does not have another character with this function so ?rArr can be used for 'implies' as ISOtech suggests -->
+        {"dArr", "8659"}, //downwards double arrow, U+21D3 ISOamsa -->
+        {"hArr", "8660"}, //left right double arrow,U+21D4 ISOamsa -->
+// <!-- Mathematical Operators -->
+        {"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 -->
+// <!-- should there be a more memorable name than 'ni'? -->
+        {"prod", "8719"}, //n-ary product = product sign,U+220F ISOamsb -->
+// <!-- prod is NOT the same character as U+03A0 'greek capital letter pi' though the same glyph might be used for both -->
+        {"sum", "8721"}, //n-ary summation, U+2211 ISOamsb -->
+// <!-- sum is NOT the same character as U+03A3 'greek capital letter sigma' though the same glyph might be used for both -->
+        {"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 -->
+// <!-- tilde operator is NOT the same character as the tilde, U+007E,although the same glyph might be used to represent both  -->
+        {"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 -->
+// <!-- note that nsup, 'not a superset of, U+2283' is not covered by the Symbol font encoding and is not included. Should it be, for symmetry?It is in ISOamsn  --> <!ENTITY nsub", "8836"},  //not a subset of, U+2284 ISOamsn -->
+        {"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 -->
+// <!-- dot operator is NOT the same character as U+00B7 middle dot -->
+// <!-- Miscellaneous Technical -->
+        {"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 -->
+// <!-- lang is NOT the same character as U+003C 'less than' or U+2039 'single left-pointing angle quotation mark' -->
+        {"rang", "9002"}, //right-pointing angle bracket = ket,U+232A ISOtech -->
+// <!-- rang is NOT the same character as U+003E 'greater than' or U+203A 'single right-pointing angle quotation mark' -->
+// <!-- Geometric Shapes -->
+        {"loz", "9674"}, //lozenge, U+25CA ISOpub -->
+// <!-- Miscellaneous Symbols -->
+        {"spades", "9824"}, //black spade suit, U+2660 ISOpub -->
+// <!-- black here seems to mean filled as opposed to hollow -->
+        {"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 -->
+
+// <!-- Latin Extended-A -->
+        {"OElig", "338"}, //  -- latin capital ligature OE,U+0152 ISOlat2 -->
+        {"oelig", "339"}, //  -- latin small ligature oe, U+0153 ISOlat2 -->
+// <!-- ligature is a misnomer, this is a separate character in some languages -->
+        {"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 -->
+// <!-- Spacing Modifier Letters -->
+        {"circ", "710"}, //  -- modifier letter circumflex accent,U+02C6 ISOpub -->
+        {"tilde", "732"}, //small tilde, U+02DC ISOdia -->
+// <!-- General Punctuation -->
+        {"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 -->
+// <!-- lsaquo is proposed but not yet ISO standardized -->
+        {"rsaquo", "8250"}, //single right-pointing angle quotation mark,U+203A ISO proposed -->
+// <!-- rsaquo is proposed but not yet ISO standardized -->
+        {"euro", "8364"}, //  -- euro sign, U+20AC NEW -->
+    };
+
+    /**
+     * <p>The set of entities supported by standard XML.</p>
+     */
+    public static final Entities XML;
+
+    /**
+     * <p>The set of entities supported by HTML 3.2.</p>
+     */
+    public static final Entities HTML32;
+
+    /**
+     * <p>The set of entities supported by HTML 4.0.</p>
+     */
+    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);
+    }
+
+    /**
+     * <p>Escapes the characters in a <code>String</code>.</p>
+     *
+     * <p>For example, if you have called addEntity(&quot;foo&quot;, 0xA1),
+     * escape(&quot;\u00A1&quot;) will return &quot;&amp;foo;&quot;</p>
+     *
+     * @param str The <code>String</code> to escape.
+     * @return A new escaped <code>String</code>.
+     */
+    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();
+    }
+
+    /**
+     * <p>Unescapes the entities in a <code>String</code>.</p>
+     *
+     * <p>For example, if you have called addEntity(&quot;foo&quot;, 0xA1),
+     * unescape(&quot;&amp;foo;&quot;) will return &quot;\u00A1&quot;</p>
+     *
+     * @param str The <code>String</code> to escape.
+     * @return A new escaped <code>String</code>.
+     */
+    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.length() == 0) {
+                    entityValue = -1;
+                } else if (entityName.charAt(0) == '#') {
+                    if (entityName.length() == 1) {
+                        entityValue = -1;
+                    } else {
+                        char charAt1 = entityName.charAt(1);
+                        try {
+                            if (charAt1 == 'x' || charAt1=='X') {
+                                entityValue = Integer.valueOf(entityName.substring(2), 16).intValue();
+                            } else {
+                                entityValue = Integer.parseInt(entityName.substring(1));
+                            }
+                        } catch (NumberFormatException ex) {
+                            entityValue = -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();
+    }
+
+}

Propchange: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/Entities.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/IllegalClassException.java
URL: http://svn.apache.org/viewcvs/directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/IllegalClassException.java?rev=370807&view=auto
==============================================================================
--- directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/IllegalClassException.java (added)
+++ directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/IllegalClassException.java Fri Jan 20 05:47:50 2006
@@ -0,0 +1,95 @@
+/*
+ * Copyright 2002-2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.mina.common.support.lang;
+
+/**
+ * <p>Thrown when an object is an instance of an unexpected type (a class or interface).
+ * This exception supplements the standard <code>IllegalArgumentException</code>
+ * by providing a more semantically rich description of the problem.</p>
+ * 
+ * <p><code>IllegalClassException</code> represents the case where a method takes
+ * in a genericly typed parameter like Object (typically because it has to due to some
+ * other interface it implements), but this implementation only actually accepts a specific
+ * type, for example String. This exception would be used in place of
+ * <code>IllegalArgumentException</code>, yet it still extends it.</p>
+ * 
+ * <pre>
+ * public void foo(Object obj) {
+ *   if (obj instanceof String == false) {
+ *     throw new IllegalClassException(String.class, obj);
+ *   }
+ *   // do something with the string
+ * }
+ * </pre>
+ * 
+ * @author Matthew Hawthorne
+ * @author Gary Gregory
+ * @author Stephen Colebourne
+ * @since 2.0
+ * @version $Id$
+ */
+public class IllegalClassException extends IllegalArgumentException {
+
+    /**
+     * <p>Instantiates with the expected type, and actual object.</p>
+     * 
+     * @param expected  the expected type
+     * @param actual  the actual object
+     * @since 2.1
+     */
+    public IllegalClassException(Class expected, Object actual) {
+        super(
+            "Expected: "
+                + safeGetClassName(expected)
+                + ", actual: "
+                + (actual == null ? "null" : actual.getClass().getName()));
+    }
+
+    /**
+     * <p>Instantiates with the expected and actual types.</p>
+     * 
+     * @param expected  the expected type
+     * @param actual  the actual type
+     */
+    public IllegalClassException(Class expected, Class actual) {
+        super(
+            "Expected: "
+                + safeGetClassName(expected)
+                + ", actual: "
+                + safeGetClassName(actual));
+    }
+
+    /**
+     * <p>Instantiates with the specified message.</p>
+     * 
+     * @param message  the exception message
+     */
+    public IllegalClassException(String message) {
+        super(message);
+    }
+
+    /**
+     * <p>Returns the class name or <code>null</code> if the class is
+     * <code>null</code>.</p>
+     * 
+     * @param cls  a <code>Class</code>
+     * @return the name of <code>cls</code>, or <code>null</code> if if <code>cls</code> is <code>null</code>.
+     */
+    private static final String safeGetClassName(Class cls) {
+        return cls == null ? null : cls.getName();
+    }
+
+}

Propchange: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/IllegalClassException.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision

Added: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/IncompleteArgumentException.java
URL: http://svn.apache.org/viewcvs/directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/IncompleteArgumentException.java?rev=370807&view=auto
==============================================================================
--- directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/IncompleteArgumentException.java (added)
+++ directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/IncompleteArgumentException.java Fri Jan 20 05:47:50 2006
@@ -0,0 +1,81 @@
+/*
+ * Copyright 2002-2005 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.mina.common.support.lang;
+
+import java.util.Arrays;
+
+/**
+ * <p>Thrown to indicate an incomplete argument to a method.
+ * This exception supplements the standard <code>IllegalArgumentException</code>
+ * by providing a more semantically rich description of the problem.</p>
+ * 
+ * <p><code>IncompleteArgumentException</code> represents the case where a method takes
+ * in a parameter that has a number of properties, some of which have not been set.
+ * A case might be a search requirements bean that must have three properties set
+ * in order for the method to run, but only one is actually set.
+ * This exception would be used in place of
+ * <code>IllegalArgumentException</code>, yet it still extends it.</p>
+ * 
+ * <pre>
+ * public void foo(PersonSearcher search) {
+ *   if (search.getSurname() == null ||
+ *       search.getForename() == null ||
+ *       search.getSex() == null) {
+ *     throw new IncompleteArgumentException("search");
+ *   }
+ *   // do something with the searcher
+ * }
+ * </pre>
+ * 
+ * @author Matthew Hawthorne
+ * @since 2.0
+ * @version $Id$
+ */
+public class IncompleteArgumentException extends IllegalArgumentException {
+
+    /**
+     * <p>Instantiates with the specified description.</p>
+     * 
+     * @param argName  a description of the incomplete argument
+     */
+    public IncompleteArgumentException(String argName) {
+        super(argName + " is incomplete.");
+    }
+
+    /**
+     * <p>Instantiates with the specified description.</p>
+     * 
+     * @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));
+    }
+
+    /**
+     * <p>Converts an array to a string without throwing an exception.</p>
+     * 
+     * @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();
+    }
+
+}

Propchange: directory/sandbox/trustin/mina-spi/core/src/main/java/org/apache/mina/common/support/lang/IncompleteArgumentException.java
------------------------------------------------------------------------------
    svn:keywords = HeadURL Id LastChangedBy LastChangedDate LastChangedRevision