You are viewing a plain text version of this content. The canonical link for it is here.
Posted to java-dev@axis.apache.org by as...@apache.org on 2005/07/11 07:04:39 UTC

svn commit: r210069 - in /webservices/axis/trunk/archive/java/scratch/ashu_jaya_venkat/jaxws/src/org/apache/axis/jaxrpc: handler/HandlerChainImpl.java utils/ utils/ClassUtils.java utils/StringUtils.java

Author: ashutosh
Date: Sun Jul 10 22:04:37 2005
New Revision: 210069

URL: http://svn.apache.org/viewcvs?rev=210069&view=rev
Log:
Some utility classes taken from Axis1.2

Added:
    webservices/axis/trunk/archive/java/scratch/ashu_jaya_venkat/jaxws/src/org/apache/axis/jaxrpc/utils/
    webservices/axis/trunk/archive/java/scratch/ashu_jaya_venkat/jaxws/src/org/apache/axis/jaxrpc/utils/ClassUtils.java
    webservices/axis/trunk/archive/java/scratch/ashu_jaya_venkat/jaxws/src/org/apache/axis/jaxrpc/utils/StringUtils.java
Modified:
    webservices/axis/trunk/archive/java/scratch/ashu_jaya_venkat/jaxws/src/org/apache/axis/jaxrpc/handler/HandlerChainImpl.java

Modified: webservices/axis/trunk/archive/java/scratch/ashu_jaya_venkat/jaxws/src/org/apache/axis/jaxrpc/handler/HandlerChainImpl.java
URL: http://svn.apache.org/viewcvs/webservices/axis/trunk/archive/java/scratch/ashu_jaya_venkat/jaxws/src/org/apache/axis/jaxrpc/handler/HandlerChainImpl.java?rev=210069&r1=210068&r2=210069&view=diff
==============================================================================
--- webservices/axis/trunk/archive/java/scratch/ashu_jaya_venkat/jaxws/src/org/apache/axis/jaxrpc/handler/HandlerChainImpl.java (original)
+++ webservices/axis/trunk/archive/java/scratch/ashu_jaya_venkat/jaxws/src/org/apache/axis/jaxrpc/handler/HandlerChainImpl.java Sun Jul 10 22:04:37 2005
@@ -19,18 +19,20 @@
 import org.apache.axis.jaxrpc.handler.soap.SOAPMessageContextImpl;
 import org.apache.axis.jaxrpc.handler.MessageContextImpl;
 
+import org.apache.axis.jaxrpc.utils.ClassUtils;
+
 public class HandlerChainImpl extends ArrayList implements HandlerChain {
 
 	private String[] roles;
 	
 	private int falseIndex = -1;
 	
-	protected List handlerInfos = new ArrayList();
+	protected List<HandlerInfo> handlerInfos = new ArrayList<HandlerInfo>();
 	
 	public static final String JAXRPC_METHOD_INFO = "jaxrpc.method.info";
 	
 	private HandlerInfo getHandlerInfo(int index){
-		return (HandlerInfo)handlerInfos.get(index);
+		return handlerInfos.get(index);
 	}
 	
 	private Handler getHandlerInstance(int index) {
@@ -47,6 +49,10 @@
 		}
 	}
 	
+	private void preInvoke(SOAPMessageContext msgContext){
+		// EMPTY FUNCTION FOR NOW, MAY USE LATER
+	}
+	
 	private void postInvoke(SOAPMessageContext msgContext) {
 		SOAPMessage message = msgContext.getMessage();
 		ArrayList oldList =  (ArrayList)msgContext.getProperty(JAXRPC_METHOD_INFO);
@@ -61,7 +67,7 @@
 		
 	}
 	
-	public HandlerChainImpl(List handlerInfos){
+	public HandlerChainImpl(List<HandlerInfo> handlerInfos){
 		this.handlerInfos = handlerInfos;
 		for(int i = 0; i < handlerInfos.size(); i++){
 			add(newHandler(getHandlerInfo(i)));
@@ -98,9 +104,11 @@
 		return list;
 	}
 	
-	public boolean handleRequest(MessageContext context) throws JAXRPCException {
-		SOAPMessageContextImpl actx = (SOAPMessageContextImpl)context;
+	public boolean handleRequest(MessageContext _context) throws JAXRPCException {
+		SOAPMessageContextImpl actx = (SOAPMessageContextImpl)_context;
 		actx.setRoles(getRoles());
+		SOAPMessageContext context = (SOAPMessageContext)_context;
+		preInvoke(context);
 		try {
 			for (int i = 0; i < size(); i++) {
 				Handler currentHandler = getHandlerInstance(i);
@@ -116,13 +124,14 @@
 			}
 			return true;
 		}finally {
-			postInvoke(actx);
+			postInvoke(context);
 		}
 	}
 
 	public boolean handleResponse(MessageContext context)
 			throws JAXRPCException {
 		SOAPMessageContextImpl scontext = (SOAPMessageContextImpl)context;
+		preInvoke(scontext);
 		try {
 			int endIdx = size() - 1;
 			if (falseIndex != -1) {
@@ -141,6 +150,7 @@
 
 	public boolean handleFault(MessageContext _context) throws JAXRPCException {
 		SOAPMessageContextImpl context = (SOAPMessageContextImpl)_context;
+		preInvoke(context);
 		try {
 			int endIdx = size() - 1;
 			if (falseIndex != -1) {

Added: webservices/axis/trunk/archive/java/scratch/ashu_jaya_venkat/jaxws/src/org/apache/axis/jaxrpc/utils/ClassUtils.java
URL: http://svn.apache.org/viewcvs/webservices/axis/trunk/archive/java/scratch/ashu_jaya_venkat/jaxws/src/org/apache/axis/jaxrpc/utils/ClassUtils.java?rev=210069&view=auto
==============================================================================
--- webservices/axis/trunk/archive/java/scratch/ashu_jaya_venkat/jaxws/src/org/apache/axis/jaxrpc/utils/ClassUtils.java (added)
+++ webservices/axis/trunk/archive/java/scratch/ashu_jaya_venkat/jaxws/src/org/apache/axis/jaxrpc/utils/ClassUtils.java Sun Jul 10 22:04:37 2005
@@ -0,0 +1,304 @@
+/*
+ * Copyright 2001-2004 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.axis.jaxrpc.utils;
+
+import java.io.InputStream;
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+
+/**
+ * Utility methods for Class Loading.
+ *
+ * @author Davanum Srinvas (dims@yahoo.com)
+ * @author Matthew Pocock (matthew_pocock@yahoo.co.uk)
+ */
+public final class ClassUtils {
+    /** default class loader */
+    private static ClassLoader defaultClassLoader
+            = ClassUtils.class.getClassLoader();
+
+    /** hash table of class loaders */
+    private static java.util.Hashtable classloaders = new java.util.Hashtable();
+
+    /**
+     * Set the default ClassLoader. If loader is null, the default loader is
+     * not changed.
+     *
+     * @param loader  the new default ClassLoader
+     */
+    public static void setDefaultClassLoader(ClassLoader loader) {
+      if (loader != null)
+          defaultClassLoader = loader;
+    }
+
+    public static ClassLoader getDefaultClassLoader() {
+        return defaultClassLoader;
+    }
+
+    /**
+     * Set the ClassLoader associated with the given className. If either the
+     * class name or the loader are null, no action is performed.
+     *
+     * @param className the name of a class
+     * @param loader the ClassLoader for the class
+     */
+    public static void setClassLoader(String className, ClassLoader loader) {
+        if (className != null && loader != null)
+            classloaders.put(className, loader);
+    }
+
+    /**
+     * Obtain the ClassLoader (if any) associated with the given
+     * className.
+     *
+     * @param className the name of a class
+     * @return class loader
+     */
+    public static ClassLoader getClassLoader(String className) {
+        if (className == null) {
+            return null;
+        }
+        return (ClassLoader) classloaders.get(className);
+    }
+
+    /**
+     * Deregister the ClassLoader for a given className.
+     *
+     * @param className the name of a class
+     */
+    public static void removeClassLoader(String className) {
+        classloaders.remove(className);
+    }
+
+
+    /**
+     * Use this method instead of Class.forName
+     *
+     * @param className Class name
+     * @return java class
+     * @throws ClassNotFoundException if the class is not found
+     */
+    public static Class forName(String className)
+            throws ClassNotFoundException {
+        return loadClass(className);
+    }
+
+    /**
+     * Use this method instead of Class.forName (String className, boolean init, ClassLoader loader)
+     *
+     * @param _className Class name
+     * @param init initialize the class
+     * @param _loader class loader
+     * @return java class
+     *
+     * @throws ClassNotFoundException if the class is not found
+     */
+    public static Class forName(
+            String _className, boolean init, ClassLoader _loader)
+            throws ClassNotFoundException {
+
+        // Create final vars for doPrivileged block
+        final String className = _className;
+        final ClassLoader loader = _loader;
+        try {
+            // Get the class within a doPrivleged block
+            Object ret =
+                AccessController.doPrivileged(
+                    new PrivilegedAction() {
+                        public Object run() {
+                            try {
+                                return Class.forName(className, true, loader);
+                            } catch (Throwable e) {
+                                return e;
+                            }
+                        }
+                    });
+            // If the class was located, return it.  Otherwise throw exception
+            if (ret instanceof Class) {
+                return (Class) ret;
+            } else if (ret instanceof ClassNotFoundException) {
+                throw (ClassNotFoundException) ret;
+            } else {
+                throw new ClassNotFoundException(_className);
+            }
+        } catch (ClassNotFoundException cnfe) {
+            return loadClass(className);
+        }
+    }
+
+    /**
+     * Loads the class from the context class loader and then falls back to
+     * getDefaultClassLoader().forName
+     *
+     * @param _className Class name
+     * @return java class
+     * @throws ClassNotFoundException if the class is not found
+     */
+    private static Class loadClass(String _className)
+            throws ClassNotFoundException {
+        // Create final vars for doPrivileged block
+        final String className = _className;
+
+        // Get the class within a doPrivleged block
+        Object ret =
+            AccessController.doPrivileged(
+                    new PrivilegedAction() {
+                        public Object run() {
+                            try {
+                                // Check if the class is a registered class then
+                                // use the classloader for that class.
+                                ClassLoader classLoader = getClassLoader(className);
+                                return Class.forName(className, true, classLoader);
+                            } catch (ClassNotFoundException cnfe) {
+                            }
+
+                            try {
+                                // Try the context class loader
+                                ClassLoader classLoader =
+                                    Thread.currentThread().getContextClassLoader();
+                                return Class.forName(className, true, classLoader);
+                            } catch (ClassNotFoundException cnfe2) {
+                                try {
+                                    // Try the classloader that loaded this class.
+                                    ClassLoader classLoader =
+                                        ClassUtils.class.getClassLoader();
+                                    return Class.forName(className, true, classLoader);
+                                } catch (ClassNotFoundException cnfe3) {
+                                    // Try the default class loader.
+                                    try {
+                                        return defaultClassLoader.loadClass(
+                                                className);
+                                    } catch (Throwable e) {
+                                        // Still not found, return exception
+                                        return e;
+                                    }
+                                }
+                            }
+                        }
+                    });
+
+        // If the class was located, return it.  Otherwise throw exception
+        if (ret instanceof Class) {
+            return (Class) ret;
+        } else if (ret instanceof ClassNotFoundException) {
+            throw (ClassNotFoundException) ret;
+        } else {
+            throw new ClassNotFoundException(_className);
+        }
+    }
+
+    /**
+     * Get an input stream from a named resource.
+     * Tries
+     * <ol>
+     * <li>the classloader that loaded "clazz" first,
+     * <li>the system classloader
+     * <li>the class "clazz" itself
+     * </ol>
+     * @param clazz class to use in the lookups
+     * @param resource resource string to look for
+     * @param checkThreadContextFirst check the thread context first?
+     * @return input stream if found, or null
+     */
+    public static InputStream getResourceAsStream(Class clazz, String resource, boolean checkThreadContextFirst) {
+        InputStream myInputStream = null;
+
+        if (checkThreadContextFirst &&
+                Thread.currentThread().getContextClassLoader() != null) {
+            // try the context class loader.
+            myInputStream =
+                    Thread.currentThread().getContextClassLoader()
+                    .getResourceAsStream(resource);
+        }
+        if (myInputStream == null) {
+            // if not found in context class loader fall back to default
+            myInputStream = getResourceAsStream(clazz, resource);
+        }
+        return myInputStream;
+    }
+
+    /**
+     * Get an input stream from a named resource.
+     * Tries
+     * <ol>
+     * <li>the classloader that loaded "clazz" first,
+     * <li>the system classloader
+     * <li>the class "clazz" itself
+     * </ol>
+     * @param clazz class to use in the lookups
+     * @param resource resource string to look for
+     * @return input stream if found, or null
+     */
+    public static InputStream getResourceAsStream(Class clazz, String resource) {
+        InputStream myInputStream = null;
+
+        if(clazz.getClassLoader()!=null) {
+            // Try the class loader that loaded this class.
+            myInputStream = clazz.getClassLoader().getResourceAsStream(resource);
+        } else {
+            // Try the system class loader.
+            myInputStream = ClassLoader.getSystemClassLoader().getResourceAsStream(resource);
+        }
+        if (myInputStream == null && Thread.currentThread().getContextClassLoader() != null) {
+            // try the context class loader.
+            myInputStream = Thread.currentThread().getContextClassLoader().getResourceAsStream(resource);
+        }
+        if (myInputStream == null) {
+            // if not found in classpath fall back to default
+            myInputStream = clazz.getResourceAsStream(resource);
+        }
+        return myInputStream;
+    }
+
+    /**
+     * Creates a new ClassLoader from a classpath specification and a parent
+     * class loader.
+     * The classpath string will be split using the system path seperator
+     * character (e.g. : or ;), just as the java system-wide class path is
+     * processed.
+     *
+     * @param classpath  the classpath String
+     * @param parent  the parent ClassLoader, or null if the default is to be
+     *     used
+     * @throws SecurityException if you don't have privilages to create
+     *         class loaders
+     * @throws IllegalArgumentException if your classpath string is silly
+     */
+    public static ClassLoader createClassLoader(String classpath,
+                                                ClassLoader parent)
+            throws SecurityException
+    {
+        String[] names = StringUtils.split(classpath, System.getProperty("path.separator").charAt(0));
+
+        URL[] urls = new URL[names.length];
+        try {
+            for(int i = 0; i < urls.length; i++)
+                urls[i] = new File(names[i]).toURL();
+        }
+        catch (MalformedURLException e) {
+          // I don't think this is possible, so I'm throwing this as an
+          // un-checked exception
+          throw (IllegalArgumentException) new IllegalArgumentException(
+                  "Unable to parse classpath: " + classpath);
+        }
+
+        return new URLClassLoader(urls, parent);
+    }
+}

Added: webservices/axis/trunk/archive/java/scratch/ashu_jaya_venkat/jaxws/src/org/apache/axis/jaxrpc/utils/StringUtils.java
URL: http://svn.apache.org/viewcvs/webservices/axis/trunk/archive/java/scratch/ashu_jaya_venkat/jaxws/src/org/apache/axis/jaxrpc/utils/StringUtils.java?rev=210069&view=auto
==============================================================================
--- webservices/axis/trunk/archive/java/scratch/ashu_jaya_venkat/jaxws/src/org/apache/axis/jaxrpc/utils/StringUtils.java (added)
+++ webservices/axis/trunk/archive/java/scratch/ashu_jaya_venkat/jaxws/src/org/apache/axis/jaxrpc/utils/StringUtils.java Sun Jul 10 22:04:37 2005
@@ -0,0 +1,454 @@
+/*
+ * Copyright 2001-2004 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.axis.jaxrpc.utils;
+
+import java.util.ArrayList;
+import java.util.List;
+import java.io.Writer;
+import java.io.IOException;
+import java.io.StringWriter;
+
+public class StringUtils {
+    private StringUtils() {
+    }
+
+    /**
+     * An empty immutable <code>String</code> array.
+     */
+    public static final String[] EMPTY_STRING_ARRAY = new String[0];
+
+    /**
+     * Tests if this string starts with the specified prefix (Ignoring whitespaces)
+     * @param prefix
+     * @param string
+     * @return boolean
+     */
+    public static boolean startsWithIgnoreWhitespaces(String prefix, String string) {
+        int index1 = 0;
+        int index2 = 0;
+        int length1 = prefix.length();
+        int length2 = string.length();
+        char ch1 = ' ';
+        char ch2 = ' ';
+        while (index1 < length1 && index2 < length2) {
+            while (index1 < length1 && Character.isWhitespace(ch1 = prefix.charAt(index1))) {
+                index1++;
+            }
+            while (index2 < length2 && Character.isWhitespace(ch2 = string.charAt(index2))) {
+                index2++;
+            }
+            if (index1 == length1 && index2 == length2) {
+                return true;
+            }
+            if (ch1 != ch2) {
+                return false;
+            }
+            index1++;
+            index2++;
+        }
+        if(index1 < length1 && index2 >= length2)
+            return false;
+        return true;
+    }
+
+    /**
+     * <p>Splits the provided text into an array, separator specified.
+     * This is an alternative to using StringTokenizer.</p>
+     *
+     * <p>The separator is not included in the returned String array.
+     * Adjacent separators are treated as one separator.</p>
+     *
+     * <p>A <code>null</code> input String returns <code>null</code>.</p>
+     *
+     * <pre>
+     * 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"]
+     * </pre>
+     *
+     * @param str  the String to parse, may be null
+     * @param separatorChar  the character used as the delimiter,
+     *  <code>null</code> splits on whitespace
+     * @return an array of parsed Strings, <code>null</code> if null String input
+     */
+    public static String[] split(String str, char separatorChar) {
+        if (str == null) {
+            return null;
+        }
+        int len = str.length();
+        if (len == 0) {
+            return 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()]);
+    }
+
+    // Empty checks
+    //-----------------------------------------------------------------------
+    /**
+     * <p>Checks if a String is empty ("") or null.</p>
+     *
+     * <pre>
+     * StringUtils.isEmpty(null)      = true
+     * StringUtils.isEmpty("")        = true
+     * StringUtils.isEmpty(" ")       = false
+     * StringUtils.isEmpty("bob")     = false
+     * StringUtils.isEmpty("  bob  ") = false
+     * </pre>
+     *
+     * <p>NOTE: This method changed in Lang version 2.0.
+     * It no longer trims the String.
+     * That functionality is available in isBlank().</p>
+     *
+     * @param str  the String to check, may be null
+     * @return <code>true</code> if the String is empty or null
+     */
+    public static boolean isEmpty(String str) {
+        return (str == null || str.length() == 0);
+    }
+
+    // Stripping
+    //-----------------------------------------------------------------------
+    /**
+     * <p>Strips whitespace from the start and end of a String.</p>
+     *
+     * <p>This removes whitespace. Whitespace is defined by
+     * {@link Character#isWhitespace(char)}.</p>
+     *
+     * <p>A <code>null</code> input String returns <code>null</code>.</p>
+     *
+     * <pre>
+     * 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"
+     * </pre>
+     *
+     * @param str  the String to remove whitespace from, may be null
+     * @return the stripped String, <code>null</code> if null String input
+     */
+    public static String strip(String str) {
+        return strip(str, null);
+    }
+
+    /**
+     * <p>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.</p>
+     *
+     * <p>A <code>null</code> input String returns <code>null</code>.
+     * An empty string ("") input returns the empty string.</p>
+     *
+     * <p>If the stripChars String is <code>null</code>, whitespace is
+     * stripped as defined by {@link Character#isWhitespace(char)}.
+     * Alternatively use {@link #strip(String)}.</p>
+     *
+     * <pre>
+     * 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"
+     * </pre>
+     *
+     * @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, <code>null</code> if null String input
+     */
+    public static String strip(String str, String stripChars) {
+        if (str == null) {
+            return str;
+        }
+        int len = str.length();
+        if (len == 0) {
+            return str;
+        }
+        int start = getStripStart(str, stripChars);
+        if (start == len) {
+            return "";
+        }
+        int end = getStripEnd(str, stripChars);
+        return (start == 0 && end == len) ? str : str.substring(start, end);
+    }
+
+    /**
+     * <p>Strips any of a set of characters from the start of a String.</p>
+     *
+     * <p>A <code>null</code> input String returns <code>null</code>.
+     * An empty string ("") input returns the empty string.</p>
+     *
+     * <p>If the stripChars String is <code>null</code>, whitespace is
+     * stripped as defined by {@link Character#isWhitespace(char)}.</p>
+     *
+     * <pre>
+     * 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  "
+     * </pre>
+     *
+     * @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, <code>null</code> if null String input
+     */
+    public static String stripStart(String str, String stripChars) {
+        int start = getStripStart(str, stripChars);
+        return (start <= 0) ? str : str.substring(start);
+    }
+
+    private static int getStripStart(String str, String stripChars) {
+        int strLen;
+        if (str == null || (strLen = str.length()) == 0) {
+            return -1;
+        }
+        int start = 0;
+        if (stripChars == null) {
+            while ((start != strLen) && Character.isWhitespace(str.charAt(start))) {
+                start++;
+            }
+        } else if (stripChars.length() == 0) {
+            return start;
+        } else {
+            while ((start != strLen) && (stripChars.indexOf(str.charAt(start)) != -1)) {
+                start++;
+            }
+        }
+        return start;
+    }
+
+    /**
+     * <p>Strips any of a set of characters from the end of a String.</p>
+     *
+     * <p>A <code>null</code> input String returns <code>null</code>.
+     * An empty string ("") input returns the empty string.</p>
+     *
+     * <p>If the stripChars String is <code>null</code>, whitespace is
+     * stripped as defined by {@link Character#isWhitespace(char)}.</p>
+     *
+     * <pre>
+     * 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"
+     * </pre>
+     *
+     * @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, <code>null</code> if null String input
+     */
+    public static String stripEnd(String str, String stripChars) {
+        int end = getStripEnd(str, stripChars);
+        return (end < 0) ? str : str.substring(0, end);
+    }
+
+    private static int getStripEnd(String str, String stripChars) {
+        int end;
+        if (str == null || (end = str.length()) == 0) {
+            return -1;
+        }
+        if (stripChars == null) {
+            while ((end != 0) && Character.isWhitespace(str.charAt(end - 1))) {
+                end--;
+            }
+        } else if (stripChars.length() == 0) {
+            return end;
+        } else {
+            while ((end != 0) && (stripChars.indexOf(str.charAt(end - 1)) != -1)) {
+                end--;
+            }
+        }
+        return end;
+    }
+
+    /**
+     * write the escaped version of a given string
+     *
+     * @param str string to be encoded
+     * @return a new escaped <code>String</code>, <code>null</code> if null string input
+     */
+    public static String escapeNumericChar(String str) {
+        if (str == null) {
+            return null;
+        }
+        try {
+            StringWriter writer = new StringWriter(str.length());
+            escapeNumericChar(writer, str);
+            return writer.toString();
+        } catch (IOException ioe) {
+            // this should never ever happen while writing to a StringWriter
+            ioe.printStackTrace();
+            return null;
+        }
+    }
+
+    /**
+     * write the escaped version of a given string
+     *
+     * @param out       writer to write this string to
+     * @param str       string to be encoded
+     */
+    public static void escapeNumericChar(Writer out, String str)
+            throws IOException {
+        if (str == null) {
+            return;
+        }
+        int length = str.length();
+        char character;
+        for (int i = 0; i < length; i++) {
+            character = str.charAt( i );
+            if (character > 0x7F) {
+                out.write("&#x");
+                out.write(Integer.toHexString(character).toUpperCase());
+                out.write(";");
+            } else {
+                out.write(character);
+            }
+        }
+    }
+
+    /**
+     * <p>Unescapes numeric character referencs found in the <code>String</code>.</p>
+     *
+     * <p>For example, it will return a unicode string which means the specified numeric
+     *    character references looks like "&#x3088;&#x3046;&#x3053;&#x305d;".</p>
+     *
+     * @param str  the <code>String</code> to unescape, may be null
+     * @return a new unescaped <code>String</code>, <code>null</code> if null string input
+     */
+    public static String unescapeNumericChar(String str) {
+        if (str == null) {
+            return null;
+        }
+        try {
+            StringWriter writer = new StringWriter(str.length());
+            unescapeNumericChar(writer, str);
+            return writer.toString();
+        } catch (IOException ioe) {
+            // this should never ever happen while writing to a StringWriter
+            ioe.printStackTrace();
+            return null;
+        }
+    }
+
+    /**
+     * <p>Unescapes numeric character references found in the <code>String</code> to a
+     * <code>Writer</code>.</p>
+     *
+     * <p>For example, it will return a unicode string which means the specified numeric
+     *    character references looks like "&#x3088;&#x3046;&#x3053;&#x305d;".</p>
+     *
+     * <p>A <code>null</code> string input has no effect.</p>
+     *
+     * @param out  the <code>Writer</code> used to output unescaped characters
+     * @param str  the <code>String</code> to unescape, may be null
+     * @throws IllegalArgumentException if the Writer is <code>null</code>
+     * @throws java.io.IOException if error occurs on underlying Writer
+     */
+    public static void unescapeNumericChar(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);
+        StringBuffer escapes = new StringBuffer(3);
+        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 character
+                    try {
+                        int value = Integer.parseInt(unicode.toString(), 16);
+                        out.write((char) value);
+                        unicode.setLength(0);
+                        // need to skip the delimiter - ';'
+                        i = i + 1;
+                        inUnicode = false;
+                    } catch (NumberFormatException nfe) {
+                        throw new RuntimeException(nfe);
+                    }
+                }
+                continue;
+            } else if (ch=='&') {
+                // Start of the escape sequence ...
+                // At least, the numeric character references require 8 bytes to
+                // describe a Unicode character like as"&#xFFFF;"
+                if (i+7 <= sz) {
+                    escapes.append(ch);
+                    escapes.append(str.charAt(i+1));
+                    escapes.append(str.charAt(i+2));
+                    if (escapes.toString().equals("&#x") && str.charAt(i+7)==';') {
+                        inUnicode = true;
+                    } else {
+                        out.write(escapes.toString());
+                    }
+                    escapes.setLength(0);
+                    // need to skip the escaping chars - '&#x'
+                    i = i + 2;
+                } else {
+                    out.write(ch);
+                }
+                continue;
+            }
+            out.write(ch);
+        }
+    }
+}