/*
 * 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.utils;

import org.apache.axis.attachments.AttachmentPart;
import org.apache.axis.attachments.OctetStream;
import org.apache.axis.components.image.ImageIO;
import org.apache.axis.components.image.ImageIOFactory;
import org.apache.axis.components.logger.LogFactory;
import org.apache.axis.types.HexBinary;
import org.apache.commons.logging.Log;

import javax.activation.DataHandler;
import javax.xml.soap.SOAPException;
import javax.xml.transform.Source;
import javax.xml.transform.stream.StreamSource;
import java.awt.*;
import java.beans.Introspector;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringReader;
import java.io.ByteArrayOutputStream;
import java.lang.reflect.Array;
import java.lang.reflect.Field;
import java.text.Collator;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Calendar;
import java.util.Collection;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.List;
import java.util.Locale;
import java.util.Set;

/** Utility class to deal with Java language related issues, such
 * as type conversions.
 *
 * @author Glen Daniels (gdaniels@apache.org)
 */
public class JavaUtils
{
    private JavaUtils() {
    }

    protected static Log log =
        LogFactory.getLog(JavaUtils.class.getName());
    
    public static final char NL = '\n';

    public static final char CR = '\r';

    /**
     * The prefered line separator
     */
    public static final String LS = System.getProperty("line.separator",
                                                       (new Character(NL)).toString());


    public static Class getWrapperClass(Class primitive)
    {
        if (primitive == int.class)
            return java.lang.Integer.class;
        else if (primitive == short.class)
            return java.lang.Short.class;
        else if (primitive == boolean.class)
            return java.lang.Boolean.class;
        else if (primitive == byte.class)
            return java.lang.Byte.class;
        else if (primitive == long.class)
            return java.lang.Long.class;
        else if (primitive == double.class)
            return java.lang.Double.class;
        else if (primitive == float.class)
            return java.lang.Float.class;
        else if (primitive == char.class)
            return java.lang.Character.class;
        
        return null;
    }
    
    public static String getWrapper(String primitive)
    {
        if (primitive.equals("int"))
            return "Integer";
        else if (primitive.equals("short"))
            return "Short";
        else if (primitive.equals("boolean"))
            return "Boolean";
        else if (primitive.equals("byte"))
            return "Byte";
        else if (primitive.equals("long"))
            return "Long";
        else if (primitive.equals("double"))
            return "Double";
        else if (primitive.equals("float"))
            return "Float";
        else if (primitive.equals("char"))
            return "Character";
        
        return null;
    }

    public static Class getPrimitiveClass(Class wrapper)
    {
        if (wrapper == java.lang.Integer.class)
            return int.class;
        else if (wrapper == java.lang.Short.class)
            return short.class;
        else if (wrapper == java.lang.Boolean.class)
            return boolean.class;
        else if (wrapper == java.lang.Byte.class)
            return byte.class;
        else if (wrapper == java.lang.Long.class)
            return long.class;
        else if (wrapper == java.lang.Double.class)
            return double.class;
        else if (wrapper == java.lang.Float.class)
            return float.class;
        else if (wrapper == java.lang.Character.class)
            return char.class;
        
        return null;
    }

    /*
         * Any builtin type that has a constructor that takes a String is a basic
         * type.
         * This is for optimization purposes, so that we don't introspect
         * primitive java types or some basic Axis types.
         */
    public static boolean isBasic(Class javaType) {
        return (javaType.isPrimitive() ||
                javaType == String.class ||
                javaType == Boolean.class ||
                javaType == Float.class ||
                javaType == Double.class ||
                Number.class.isAssignableFrom(javaType) ||
                javaType == org.apache.axis.types.Day.class ||
                javaType == org.apache.axis.types.Duration.class ||
                javaType == org.apache.axis.types.Entities.class ||
                javaType == org.apache.axis.types.Entity.class ||
                javaType == HexBinary.class ||
                javaType == org.apache.axis.types.Id.class ||
                javaType == org.apache.axis.types.IDRef.class ||
                javaType == org.apache.axis.types.IDRefs.class ||
                javaType == org.apache.axis.types.Language.class ||
                javaType == org.apache.axis.types.Month.class ||
                javaType == org.apache.axis.types.MonthDay.class ||
                javaType == org.apache.axis.types.Name.class ||
                javaType == org.apache.axis.types.NCName.class ||
                javaType == org.apache.axis.types.NegativeInteger.class ||
                javaType == org.apache.axis.types.NMToken.class ||
                javaType == org.apache.axis.types.NMTokens.class ||
                javaType == org.apache.axis.types.NonNegativeInteger.class ||
                javaType == org.apache.axis.types.NonPositiveInteger.class ||
                javaType == org.apache.axis.types.NormalizedString.class ||
                javaType == org.apache.axis.types.PositiveInteger.class ||
                javaType == org.apache.axis.types.Time.class ||
                javaType == org.apache.axis.types.Token.class ||
                javaType == org.apache.axis.types.UnsignedByte.class ||
                javaType == org.apache.axis.types.UnsignedInt.class ||
                javaType == org.apache.axis.types.UnsignedLong.class ||
                javaType == org.apache.axis.types.UnsignedShort.class ||
                javaType == org.apache.axis.types.URI.class ||
                javaType == org.apache.axis.types.Year.class ||
                javaType == org.apache.axis.types.YearMonth.class);
    }

    /**
     * It the argument to the convert(...) method implements
     * the ConvertCache interface, the convert(...) method
     * will use the set/get methods to store and retrieve
     * converted values.
     **/
    public interface ConvertCache {
        /**
         * Set/Get converted values of the convert method.
         **/
        public void setConvertedValue(Class cls, Object value);
        public Object getConvertedValue(Class cls);
        /**
         * Get the destination array class described by the xml
         **/
        public Class getDestClass();
    }

    /** Utility function to convert an Object to some desired Class.
     *
     * Right now this works for:
     *     arrays <-> Lists,
     *     Holders <-> held values
     * @param arg the array to convert
     * @param destClass the actual class we want
     */
    public static Object convert(Object arg, Class destClass)
    {
        if (destClass == null) {
            return arg;
        }

        Class argHeldType = null;
        if (arg != null) {
            argHeldType = getHolderValueType(arg.getClass());
        }

        if (arg != null && argHeldType == null && destClass.isAssignableFrom(arg.getClass())) {
            return arg;
        }

        if (log.isDebugEnabled()) {
            String clsName = "null";
            if (arg != null) clsName = arg.getClass().getName();
            log.debug( Messages.getMessage("convert00", clsName, destClass.getName()));
        }

        // See if a previously converted value is stored in the argument.
        Object destValue = null;
        if (arg instanceof ConvertCache) {
            destValue = (( ConvertCache) arg).getConvertedValue(destClass);
            if (destValue != null)
                return destValue;
        }

        // Get the destination held type or the argument held type if they exist
        Class destHeldType = getHolderValueType(destClass);

        // Convert between Axis special purpose HexBinary and byte[]
        if (arg instanceof HexBinary &&
            destClass == byte[].class) {
            return ((HexBinary) arg).getBytes();
        } else if (arg instanceof byte[] &&
                   destClass == HexBinary.class) {
            return new HexBinary((byte[]) arg);
        }

        // Convert between Calendar and Date
        if (arg instanceof Calendar && destClass == Date.class) {
            return ((Calendar) arg).getTime();
        }
        if (arg instanceof Date && destClass == Calendar.class) {
        	Calendar calendar = Calendar.getInstance();
        	calendar.setTime((Date) arg);
            return calendar;
        }

        // Convert between Calendar and java.sql.Date
        if (arg instanceof Calendar && destClass == java.sql.Date.class) {
            return new java.sql.Date(((Calendar) arg).getTime().getTime());
        }

        // Convert between HashMap and Hashtable
        if (arg instanceof HashMap && destClass == Hashtable.class) {
            return new Hashtable((HashMap)arg);
        }

        // Convert an AttachmentPart to the given destination class.
        if (isAttachmentSupported() &&
                (arg instanceof InputStream || arg instanceof AttachmentPart || arg instanceof DataHandler)) {
            try {
                String destName = destClass.getName();
                if (destClass == String.class
                        || destClass == OctetStream.class
                        || destClass == byte[].class
                        || destClass == Image.class
                        || destClass == Source.class
                        || destClass == DataHandler.class
                        || destName.equals("javax.mail.internet.MimeMultipart")) {
                    DataHandler handler = null;
                    if (arg instanceof AttachmentPart) {
                        handler = ((AttachmentPart) arg).getDataHandler();
                    }
                    else if (arg instanceof DataHandler) {
                        handler = (DataHandler) arg;
                    }
                    if (destClass == Image.class) {
                        // Note:  An ImageIO component is required to process an Image
                        // attachment, but if the image would be null
                        // (is.available == 0) then ImageIO component isn't needed
                        // and we can return null.
                        InputStream is = (InputStream) handler.getContent();
                        if (is.available() == 0) {
                            return null;
                        }
                        else {
                            ImageIO imageIO = ImageIOFactory.getImageIO();
                            if (imageIO != null) {
                                return getImageFromStream(is);
                            }
                            else {
                                log.info(Messages.getMessage("needImageIO"));
                                return arg;
                            }
                        }
                    }
                    else if (destClass == javax.xml.transform.Source.class) {
                        // For a reason unknown to me, the handler's
                        // content is a String.  Convert it to a
                        // StreamSource.
                        return new StreamSource(new StringReader(
                                (String) handler.getContent()));
                    }
                    else if (destClass == OctetStream.class || destClass == byte[].class) {
                        InputStream in = null;
                        if (arg instanceof InputStream) {
                            in = (InputStream) arg;
                        } else {
                            in = (InputStream)handler.getContent();
                        }
                        ByteArrayOutputStream baos = new ByteArrayOutputStream();
                        int byte1 = -1;
                        while((byte1 = in.read())!=-1)
                            baos.write(byte1);
                        return new OctetStream(baos.toByteArray());
                    }
                    else if (destClass == DataHandler.class) {
                        return handler;
                    }
                    else {
                        return handler.getContent();
                    }
                }
            }
            catch (IOException ioe) {
            }
            catch (SOAPException se) {
            }
        }

        // If the destination is an array and the source
        // is a suitable component, return an array with 
        // the single item.
        if (arg != null &&
            destClass.isArray() &&
            !destClass.getComponentType().equals(Object.class) &&
            destClass.getComponentType().isAssignableFrom(arg.getClass())) {
            Object array = 
                Array.newInstance(destClass.getComponentType(), 1);
            Array.set(array, 0, arg);
            return array;
        }

        // in case destClass is array and arg is ArrayOfT class. (ArrayOfT -> T[])
        if (arg != null && destClass.isArray()) {
            Object newArg = ArrayUtil.convertObjectToArray(arg, destClass);            
            if (newArg == null 
                    || (newArg != ArrayUtil.NON_CONVERTABLE && newArg != arg)) {
                return newArg;
            }            
        }
               
        // in case arg is ArrayOfT and destClass is an array. (T[] -> ArrayOfT)
        if (arg != null && arg.getClass().isArray()) {			
            Object newArg = ArrayUtil.convertArrayToObject(arg, destClass);
            if (newArg != null)
                return newArg;
        }       

        // Return if no conversion is available
        if (!(arg instanceof Collection ||
              (arg != null && arg.getClass().isArray())) &&
            ((destHeldType == null && argHeldType == null) ||
             (destHeldType != null && argHeldType != null))) {
            return arg;
        }

        // Take care of Holder conversion
        if (destHeldType != null) {
            // Convert arg into Holder holding arg.
            Object newArg = convert(arg, destHeldType);
            Object argHolder = null;
            try {
                argHolder = destClass.newInstance();
                setHolderValue(argHolder, newArg);
                return argHolder;
            } catch (Exception e) {
                return arg;
            }
        } else if (argHeldType != null) {
            // Convert arg into the held type
            try {
                Object newArg = getHolderValue(arg);
                return convert(newArg, destClass);
            } catch (HolderException e) {
                return arg;
            }
        }

        // Flow to here indicates that neither arg or destClass is a Holder

        // Check to see if the argument has a prefered destination class.
        if (arg instanceof ConvertCache &&
            (( ConvertCache) arg).getDestClass() != destClass) {
            Class hintClass = ((ConvertCache) arg).getDestClass();
            if (hintClass != null &&
                hintClass.isArray() &&
                destClass.isArray() &&
                destClass.isAssignableFrom(hintClass)) {
                destClass = hintClass;
                destValue = ((ConvertCache) arg).getConvertedValue(destClass);
                if (destValue != null)
                    return destValue;
            }
        }
        
        if (arg == null) {
            return arg;
        }

        // The arg may be an array or List 
        int length = 0;
        if (arg.getClass().isArray()) {
            length = Array.getLength(arg);
        } else {
            length = ((Collection) arg).size();
        }
        if (destClass.isArray()) {
            if (destClass.getComponentType().isPrimitive()) {

                Object array = Array.newInstance(destClass.getComponentType(),
                                                 length);
                // Assign array elements
                if (arg.getClass().isArray()) {
                    for (int i = 0; i < length; i++) {
                        Array.set(array, i, Array.get(arg, i));
                    }
                } else {
                    int idx = 0;
                    for (Iterator i = ((Collection)arg).iterator();
                            i.hasNext();) {
                        Array.set(array, idx++, i.next());
                    }
                }
                destValue = array;

            } else {
                Object [] array;
                try {
                    array = (Object [])Array.newInstance(destClass.getComponentType(),
                                                         length);
                } catch (Exception e) {
                    return arg;
                }

                // Use convert to assign array elements.
                if (arg.getClass().isArray()) {
                    for (int i = 0; i < length; i++) {
                        array[i] = convert(Array.get(arg, i),
                                           destClass.getComponentType());
                    }
                } else {
                    int idx = 0;
                    for (Iterator i = ((Collection)arg).iterator();
                            i.hasNext();) {
                        array[idx++] = convert(i.next(),
                                           destClass.getComponentType());
                    }
                }
                destValue = array;
            }
        }
        else if (Collection.class.isAssignableFrom(destClass)) {
            Collection newList = null;
            try {
                // if we are trying to create an interface, build something
                // that implements the interface
                if (destClass == Collection.class || destClass == List.class) {
                    newList = new ArrayList();
                } else if (destClass == Set.class) {
                    newList = new HashSet();
                } else {
                    newList = (Collection)destClass.newInstance();
                }
            } catch (Exception e) {
                // Couldn't build one for some reason... so forget it.
                return arg;
            }

            if (arg.getClass().isArray()) {
                for (int j = 0; j < length; j++) {
                    newList.add(Array.get(arg, j));
                }
            } else {
                for (Iterator j = ((Collection)arg).iterator();
                            j.hasNext();) {
                    newList.add(j.next());
                }
            }
            destValue = newList;
        }
        else {
            destValue = arg;
        }

        // Store the converted value in the argument if possible.
        if (arg instanceof ConvertCache) {
            (( ConvertCache) arg).setConvertedValue(destClass, destValue);
        }
        return destValue;
    }

    public static boolean isConvertable(Object obj, Class dest)
    {
        return isConvertable(obj, dest, false);
    }

    public static boolean isConvertable(Object obj, Class dest, boolean isEncoded)
    {
        Class src = null;
        
        if (obj != null) {
            if (obj instanceof Class) {
                src = (Class)obj;
            } else {
                src = obj.getClass();
            }
        } else {
            if(!dest.isPrimitive())
                return true;
        }
        
        if (dest == null)
            return false;
        
        if (src != null) {
            // If we're directly assignable, we're good.
            if (dest.isAssignableFrom(src))
                return true;

            //Allow mapping of Map's to Map's
            if (java.util.Map.class.isAssignableFrom(dest) &&
                java.util.Map.class.isAssignableFrom(src)) {
                  return true;
            }

            // If it's a wrapping conversion, we're good.
            if (getWrapperClass(src) == dest)
                return true;
            if (getWrapperClass(dest) == src)
                return true;
            
            // If it's List -> Array or vice versa, we're good.
            if ((Collection.class.isAssignableFrom(src) || src.isArray()) &&
                (Collection.class.isAssignableFrom(dest) || dest.isArray()) &&
                (src.getComponentType() == Object.class || 
                 src.getComponentType() == null ||
                 dest.getComponentType() == Object.class ||
                 dest.getComponentType() == null ||
                 isConvertable(src.getComponentType(), dest.getComponentType())))
                    return true;
            
            // If destination is an array, and src is a component, we're good
            // if we're not encoded!
            if (!isEncoded && dest.isArray() &&
//                !dest.getComponentType().equals(Object.class) &&
                dest.getComponentType().isAssignableFrom(src)) 
                return true;

            if ((src == HexBinary.class && dest == byte[].class) ||
                (src == byte[].class && dest == HexBinary.class))
                return true;
            
            // Allow mapping of Calendar to Date
            if (Calendar.class.isAssignableFrom(src) && dest == Date.class)
                return true;

            // Allow mapping of Date to Calendar
            if (Date.class.isAssignableFrom(src) && dest == Calendar.class)
                return true;

            // Allow mapping of Calendar to java.sql.Date
            if (Calendar.class.isAssignableFrom(src) && dest == java.sql.Date.class)
                return true;
        }
        
        Class destHeld = JavaUtils.getHolderValueType(dest);
        // Can always convert a null to an empty holder
        if (src == null)
            return (destHeld != null);
        
        if (destHeld != null) {
            if (destHeld.isAssignableFrom(src) || isConvertable(src, destHeld))
                return true;
        }

        // If it's holder -> held or held -> holder, we're good
        Class srcHeld = JavaUtils.getHolderValueType(src);
        if (srcHeld != null) {
            if (dest.isAssignableFrom(srcHeld) || isConvertable(srcHeld, dest))
                return true;
        }

        // If it's a MIME type mapping and we want a DataHandler,
        // then we're good.
        if (dest.getName().equals("javax.activation.DataHandler")) {
            String name = src.getName();
            if (src == String.class
                    || src == java.awt.Image.class
                    || src == OctetStream.class
                    || name.equals("javax.mail.internet.MimeMultipart")
                    || name.equals("javax.xml.transform.Source"))
                return true;
        }

        if (src.getName().equals("javax.activation.DataHandler")) {
            if (dest ==  byte[].class)
                return true;
            if (dest.isArray() && dest.getComponentType() == byte[].class)
                return true;
        }

        if (dest.getName().equals("javax.activation.DataHandler")) {
            if (src ==  Object[].class)
                return true;
            if (src.isArray() && src.getComponentType() == Object[].class)
                return true;
        }

        if (obj instanceof java.io.InputStream) {
            if (dest ==  OctetStream.class)
                return true;
        }
        
        if (src.isPrimitive()) {
            return isConvertable(getWrapperClass(src),dest);
        }
        
        // ArrayOfT -> T[] ? 
        if (dest.isArray()) {        	
        	if (ArrayUtil.isConvertable(src, dest) == true)
        		return true;
        } 
        
        // T[] -> ArrayOfT ?
        if (src.isArray()) {
        	if (ArrayUtil.isConvertable(src, dest) == true)
        		return true;
        }
        
        return false;
    }

    public static Image getImageFromStream(InputStream is) {
        try {
            return ImageIOFactory.getImageIO().loadImage(is);
        }
        catch (Throwable t) {
            return null;
        }
    } // getImageFromStream
    
    /**
     * These are java keywords as specified at the following URL (sorted alphabetically).
     * http://java.sun.com/docs/books/jls/second_edition/html/lexical.doc.html#229308
     * Note that false, true, and null are not strictly keywords; they are literal values,
     * but for the purposes of this array, they can be treated as literals.
     *    ****** PLEASE KEEP THIS LIST SORTED IN ASCENDING ORDER ******
     */
    static final String keywords[] =
    {
        "abstract",  "assert",       "boolean",    "break",      "byte",      "case",
        "catch",     "char",         "class",      "const",     "continue",
        "default",   "do",           "double",     "else",      "extends",
        "false",     "final",        "finally",    "float",     "for",
        "goto",      "if",           "implements", "import",    "instanceof",
        "int",       "interface",    "long",       "native",    "new",
        "null",      "package",      "private",    "protected", "public",
        "return",    "short",        "static",     "strictfp",  "super",
        "switch",    "synchronized", "this",       "throw",     "throws",
        "transient", "true",         "try",        "void",      "volatile",
        "while"
    };

    /** Collator for comparing the strings */
    static final Collator englishCollator = Collator.getInstance(Locale.ENGLISH);

    /** Use this character as suffix */
    static final char keywordPrefix = '_';

    /**
     * isJavaId
     * Returns true if the name is a valid java identifier.
     * @param id to check
     * @return boolean true/false
     **/
    public static boolean isJavaId(String id) {
        if (id == null || id.equals("") || isJavaKeyword(id))
            return false;
        if (!Character.isJavaIdentifierStart(id.charAt(0)))
            return false;
        for (int i=1; i<id.length(); i++)
            if (!Character.isJavaIdentifierPart(id.charAt(i)))
                return false;
        return true;
    }

    /**
     * checks if the input string is a valid java keyword.
     * @return boolean true/false
     */
    public static boolean isJavaKeyword(String keyword) {
      return (Arrays.binarySearch(keywords, keyword, englishCollator) >= 0);
    }

    /**
     * Turn a java keyword string into a non-Java keyword string.  (Right now
     * this simply means appending an underscore.)
     */
    public static String makeNonJavaKeyword(String keyword){
        return  keywordPrefix + keyword;
     }

    /**
     * Converts text of the form
     * Foo[] to the proper class name for loading [LFoo
     */
    public static String getLoadableClassName(String text) {
        if (text == null ||
            text.indexOf("[") < 0 ||
            text.charAt(0) == '[')
            return text;
        String className = text.substring(0,text.indexOf("["));
        if (className.equals("byte"))
            className = "B";
        else if (className.equals("char"))
            className = "C";
        else if (className.equals("double"))
            className = "D";
        else if (className.equals("float"))
            className = "F";
        else if (className.equals("int"))
            className = "I";
        else if (className.equals("long"))
            className = "J";
        else if (className.equals("short"))
            className = "S";
        else if (className.equals("boolean"))
            className = "Z";
        else
            className = "L" + className + ";";
        int i = text.indexOf("]");
        while (i > 0) {
            className = "[" + className;
            i = text.indexOf("]", i+1);
        }
        return className;
    }

    /**
     * Converts text of the form
     * [LFoo to the Foo[]
     */
    public static String getTextClassName(String text) {
        if (text == null ||
            text.indexOf("[") != 0)
            return text;
        String className = "";
        int index = 0;
        while(index < text.length() &&
              text.charAt(index) == '[') {
            index ++;
            className += "[]";
        }
        if (index < text.length()) {
            if (text.charAt(index)== 'B')
                className = "byte" + className;
            else if (text.charAt(index) == 'C')
                className = "char" + className;
            else if (text.charAt(index) == 'D')
                className = "double" + className;
            else if (text.charAt(index) == 'F')
                className = "float" + className;
            else if (text.charAt(index) == 'I')
                className = "int" + className;
            else if (text.charAt(index) == 'J')
                className = "long" + className;
            else if (text.charAt(index) == 'S')
                className = "short" + className;
            else if (text.charAt(index) == 'Z')
                className = "boolean" + className;
            else {
                className = text.substring(index+1, text.indexOf(";")) + className;
            }
        }
        return className;
    }

    /**
     * Map an XML name to a Java identifier per
     * the mapping rules of JSR 101 (in version 1.0 this is
     * "Chapter 20: Appendix: Mapping of XML Names"
     * 
     * @param name is the xml name
     * @return the java name per JSR 101 specification
     */
    public static String xmlNameToJava(String name)
    {
        // protect ourselves from garbage
        if (name == null || name.equals(""))
            return name;

        char[] nameArray = name.toCharArray();
        int nameLen = name.length();
        StringBuffer result = new StringBuffer(nameLen);
        boolean wordStart = false;

        // The mapping indicates to convert first character.
        int i = 0;
        while (i < nameLen
                && (isPunctuation(nameArray[i])
                || !Character.isJavaIdentifierStart(nameArray[i]))) {
            i++;
        }
        if (i < nameLen) {
            // Decapitalization code used to be here, but we use the
            // Introspector function now after we filter out all bad chars.
            
            result.append(nameArray[i]);
            //wordStart = !Character.isLetter(nameArray[i]);
            wordStart = !Character.isLetter(nameArray[i]) && nameArray[i] != "_".charAt(0);
        }
        else {
            // The identifier cannot be mapped strictly according to
            // JSR 101
            if (Character.isJavaIdentifierPart(nameArray[0])) {
                result.append("_" + nameArray[0]);
            }
            else {
                // The XML identifier does not contain any characters
                // we can map to Java.  Using the length of the string
                // will make it somewhat unique.
                result.append("_" + nameArray.length);
            }
        }

        // The mapping indicates to skip over
        // all characters that are not letters or
        // digits.  The first letter/digit
        // following a skipped character is
        // upper-cased.
        for (++i; i < nameLen; ++i) {
            char c = nameArray[i];

            // if this is a bad char, skip it and remember to capitalize next
            // good character we encounter
            if (isPunctuation(c) || !Character.isJavaIdentifierPart(c)) {
                wordStart = true;
                continue;
            }
            if (wordStart && Character.isLowerCase(c)) {
                result.append(Character.toUpperCase(c));
            }
            else {
                result.append(c);
            }
            // If c is not a character, but is a legal Java
            // identifier character, capitalize the next character.
            // For example:  "22hi" becomes "22Hi"
            //wordStart = !Character.isLetter(c);
            wordStart = !Character.isLetter(c) && c != "_".charAt(0);
        }

        // covert back to a String
        String newName = result.toString();
        
        // Follow JavaBean rules, but we need to check if the first 
        // letter is uppercase first
        if (Character.isUpperCase(newName.charAt(0)))
            newName = Introspector.decapitalize(newName);

        // check for Java keywords
        if (isJavaKeyword(newName))
            newName = makeNonJavaKeyword(newName);

        return newName;
    } // xmlNameToJava

    /**
     * Is this an XML punctuation character?
     */
    private static boolean isPunctuation(char c)
    {
        return '-' == c
            || '.' == c
            || ':' == c
            || '\u00B7' == c
            || '\u0387' == c
            || '\u06DD' == c
            || '\u06DE' == c;
    } // isPunctuation


    /**
     * replace:
     * Like String.replace except that the old new items are strings.
     *
     * @param name string
     * @param oldT old text to replace
     * @param newT new text to use
     * @return replacement string
     **/
    public static final String replace (String name,
                                        String oldT, String newT) {

        if (name == null) return "";

        // Create a string buffer that is twice initial length.
        // This is a good starting point.
        StringBuffer sb = new StringBuffer(name.length()* 2);

        int len = oldT.length ();
        try {
            int start = 0;
            int i = name.indexOf (oldT, start);

            while (i >= 0) {
                sb.append(name.substring(start, i));
                sb.append(newT);
                start = i+len;
                i = name.indexOf(oldT, start);
            }
            if (start < name.length())
                sb.append(name.substring(start));
        } catch (NullPointerException e) {
        }

        return new String(sb);
    }

    /**
     * Determines if the Class is a Holder class. If so returns Class of held type
     * else returns null
     * @param type the suspected Holder Class
     * @return class of held type or null
     */
    public static Class getHolderValueType(Class type) {
        if (type != null) {
            Class[] intf = type.getInterfaces();
            boolean isHolder = false;
            for (int i=0; i<intf.length && !isHolder; i++) {
                if (intf[i] == javax.xml.rpc.holders.Holder.class) {
                    isHolder = true;
                }
            }
            if (isHolder == false) {
                return null;
            }

            // Holder is supposed to have a public value field.
            java.lang.reflect.Field field;
            try {
                field = type.getField("value");
            } catch (Exception e) {
                field = null;
            }
            if (field != null) {
                return field.getType();
            }
        }
        return null;
    }

    /**
     * Gets the Holder value.
     * @param holder Holder object
     * @return value object
     */
    public static Object getHolderValue(Object holder) throws HolderException {
        if (!(holder instanceof javax.xml.rpc.holders.Holder)) {
            throw new HolderException(Messages.getMessage("badHolder00"));
        }
        try {
            Field valueField = holder.getClass().getField("value");
            return valueField.get(holder);
        } catch (Exception e) {
          throw new HolderException(Messages.getMessage("exception01", e.getMessage()));
        }
    }

    /**
     * Sets the Holder value.
     * @param holder Holder object
     * @param value is the object value
     */
    public static void setHolderValue(Object holder, Object value) throws HolderException {
        if (!(holder instanceof javax.xml.rpc.holders.Holder)) {
            throw new HolderException(Messages.getMessage("badHolder00"));
        }
        try {
            Field valueField = holder.getClass().getField("value");
            if (valueField.getType().isPrimitive()) {
                if (value == null)
                    ;  // Don't need to set anything
                else
                    valueField.set(holder, value);  // Automatically unwraps value to primitive
            } else {
                valueField.set(holder, value);
            }
        } catch (Exception e) {
          throw new HolderException(Messages.getMessage("exception01", e.getMessage()));
        }
    }
    public static class HolderException extends Exception
    {
        public HolderException(String msg) { super(msg); }
    }

    
    /**
     * Used to cache a result from IsEnumClassSub(). 
     * Class->Boolean mapping.
     */
    private static HashMap enumMap = new HashMap();
    
    /**
     * Determine if the class is a JAX-RPC enum class.
     * An enumeration class is recognized by
     * a getValue() method, a toString() method, a fromString(String) method
     * a fromValue(type) method and the lack
     * of a setValue(type) method
     */
    public static boolean isEnumClass(Class cls) {
        Boolean b = (Boolean)enumMap.get(cls);
        if (b == null) {
            b = (isEnumClassSub(cls)) ? Boolean.TRUE : Boolean.FALSE;
            enumMap.put(cls, b);
        }
        return b.booleanValue();
    }

    private static boolean isEnumClassSub(Class cls) {
        try {
            java.lang.reflect.Method[] methods = cls.getMethods();
            java.lang.reflect.Method getValueMethod = null, 
                fromValueMethod = null,
                setValueMethod = null, fromStringMethod = null;
            
            // linear search: in practice, this is faster than
            // sorting/searching a short array of methods.
            for (int i = 0; i < methods.length; i++) {
                String name = methods[i].getName();

                if (name.equals("getValue")
                    && methods[i].getParameterTypes().length == 0) { // getValue()
                    getValueMethod = methods[i];
                } else if (name.equals("fromString")) { // fromString(String s)
                    Object[] params = methods[i].getParameterTypes();
                    if (params.length == 1
                        && params[0] == String.class) {
                        fromStringMethod = methods[i];
                    }
                } else if (name.equals("fromValue")
                           && methods[i].getParameterTypes().length == 1) { // fromValue(Something s)
                    fromValueMethod = methods[i];
                } else if (name.equals("setValue")
                           && methods[i].getParameterTypes().length == 1) { // setValue(Something s)
                    setValueMethod = methods[i];
                }
            }

            // must have getValue and fromString, but not setValue
            // must also have toString(), but every Object subclass has that, so
            // no need to check for it.
            if (null != getValueMethod && null != fromStringMethod) {
                if (null != setValueMethod
                    && setValueMethod.getParameterTypes().length == 1
                    && getValueMethod.getReturnType() == setValueMethod.getParameterTypes()[0]) {
                    // setValue exists: return false
                    return false;
                } else {
                    return true;
                }
            } else {
                return false;
            }
        } catch (java.lang.SecurityException e) {
            return false;
        } // end of catch
    }

    public static String stackToString(Throwable e){
      java.io.StringWriter sw= new java.io.StringWriter(1024); 
      java.io.PrintWriter pw= new java.io.PrintWriter(sw); 
      e.printStackTrace(pw);
      pw.close();
      return sw.toString();
    }

    /**
     * Tests the String 'value':
     *   return 'false' if its 'false', '0', or 'no' - else 'true'
     * 
     * Follow in 'C' tradition of boolean values:
     * false is specific (0), everything else is true;
     */
    public static final boolean isTrue(String value) {
        return !isFalseExplicitly(value);
    }

    /**
     * Tests the String 'value':
     *   return 'true' if its 'true', '1', or 'yes' - else 'false'
     */
    public static final boolean isTrueExplicitly(String value) {
        return value != null  &&
               (value.equalsIgnoreCase("true")  ||
                value.equals("1")  ||
                value.equalsIgnoreCase("yes"));
    }

    /**
     * Tests the Object 'value':
     *   if its null, return default.
     *   if its a Boolean, return booleanValue()
     *   if its an Integer,  return 'false' if its '0' else 'true'
     *   if its a String, return isTrueExplicitly((String)value).
     *   All other types return 'true'
     */
    public static final boolean isTrueExplicitly(Object value, boolean defaultVal) {
        if ( value == null ) return defaultVal;
        if ( value instanceof Boolean ) {
            return ((Boolean)value).booleanValue();
        }
        if ( value instanceof Integer ) {
            return ((Integer)value).intValue() != 0;
        }
        if ( value instanceof String ) {
            return isTrueExplicitly( (String)value );
        }
        return true;
    }
    
    public static final boolean isTrueExplicitly(Object value) {
        return isTrueExplicitly(value, false);
    }

    /**
     * Tests the Object 'value':
     *   if its null, return default.
     *   if its a Boolean, return booleanValue()
     *   if its an Integer,  return 'false' if its '0' else 'true'
     *   if its a String, return 'false' if its 'false', 'no', or '0' - else 'true'
     *   All other types return 'true'
     */
    public static final boolean isTrue(Object value, boolean defaultVal) {
        return !isFalseExplicitly(value, !defaultVal);
    }
    
    public static final boolean isTrue(Object value) {
        return isTrue(value, false);
    }
    
    /**
     * Tests the String 'value':
     *   return 'true' if its 'false', '0', or 'no' - else 'false'
     * 
     * Follow in 'C' tradition of boolean values:
     * false is specific (0), everything else is true;
     */
    public static final boolean isFalse(String value) {
        return isFalseExplicitly(value);
    }

    /**
     * Tests the String 'value':
     *   return 'true' if its null, 'false', '0', or 'no' - else 'false'
     */
    public static final boolean isFalseExplicitly(String value) {
        return value == null  ||
               value.equalsIgnoreCase("false")  ||
               value.equals("0")  ||
               value.equalsIgnoreCase("no");
    }
    
    /**
     * Tests the Object 'value':
     *   if its null, return default.
     *   if its a Boolean, return !booleanValue()
     *   if its an Integer,  return 'true' if its '0' else 'false'
     *   if its a String, return isFalseExplicitly((String)value).
     *   All other types return 'false'
     */
    public static final boolean isFalseExplicitly(Object value, boolean defaultVal) {
        if ( value == null ) return defaultVal;
        if ( value instanceof Boolean ) {
            return !((Boolean)value).booleanValue();
        }
        if ( value instanceof Integer ) {
            return ((Integer)value).intValue() == 0;
        }
        if ( value instanceof String ) {
            return isFalseExplicitly( (String)value );
        }
        return false;
    }
    
    public static final boolean isFalseExplicitly(Object value) {
        return isFalseExplicitly(value, true);
    }

    /**
     * Tests the Object 'value':
     *   if its null, return default.
     *   if its a Boolean, return booleanValue()
     *   if its an Integer,  return 'false' if its '0' else 'true'
     *   if its a String, return 'false' if its 'false', 'no', or '0' - else 'true'
     *   All other types return 'true'
     */
    public static final boolean isFalse(Object value, boolean defaultVal) {
        return isFalseExplicitly(value, defaultVal);
    }
    
    public static final boolean isFalse(Object value) {
        return isFalse(value, true);
    }
    
    /**
     * Given the MIME type string, return the Java mapping.
     */
    public static String mimeToJava(String mime) {
        if ("image/gif".equals(mime) || "image/jpeg".equals(mime)) {
            return "java.awt.Image";
        }
        else if ("text/plain".equals(mime)) {
            return "java.lang.String";
        }
        else if ("text/xml".equals(mime) || "application/xml".equals(mime)) {
            return "javax.xml.transform.Source";
        }
        else if ("application/octet-stream".equals(mime)||
                 "application/octetstream".equals(mime)) {
            return "org.apache.axis.attachments.OctetStream";
        }
        else if (mime != null && mime.startsWith("multipart/")) {
            return "javax.mail.internet.MimeMultipart";
        }
        else {
            return "javax.activation.DataHandler";
        }
    } // mimeToJava

    //avoid testing and possibly failing everytime.
    private static boolean checkForAttachmentSupport = true;
    private static boolean attachmentSupportEnabled = false;

    /**
     * Determine whether attachments are supported by checking if the following
     * classes are available:  javax.activation.DataHandler,
     * javax.mail.internet.MimeMultipart.
     */
    public static synchronized boolean isAttachmentSupported() {

        if (checkForAttachmentSupport) {
            //aviod testing and possibly failing everytime.
            checkForAttachmentSupport = false;
            try {
                // Attempt to resolve DataHandler and MimeMultipart and
                // javax.xml.transform.Source, all necessary for full
                // attachment support
                ClassUtils.forName("javax.activation.DataHandler");
                ClassUtils.forName("javax.mail.internet.MimeMultipart");
                attachmentSupportEnabled = true;
            } catch (Throwable t) {
            }
            log.debug(Messages.getMessage("attachEnabled") + "  " +
                    attachmentSupportEnabled);
            if(!attachmentSupportEnabled) {
                log.warn(Messages.getMessage("attachDisabled"));
            }
        }

        return attachmentSupportEnabled;
    } // isAttachmentSupported

    /**
     * Makes the value passed in <code>initValue</code> unique among the
     * {@link String} values contained in <code>values</code> by suffixing
     * it with a decimal digit suffix.
     */
    public static String  getUniqueValue(Collection values, String initValue) {

        if (!values.contains(initValue))  {
            return  initValue;
        }
        else  {

            StringBuffer   unqVal = new StringBuffer(initValue);
            int   beg = unqVal.length(),  cur,  end;
            while (Character.isDigit(unqVal.charAt(beg - 1)))  {
                beg--;
            }
            if (beg == unqVal.length())  {
                unqVal.append('1');
            }
            cur = end = unqVal.length() - 1;

            while (values.contains(unqVal.toString()))  {

                if (unqVal.charAt(cur) < '9')  {
                    unqVal.setCharAt(cur, (char) (unqVal.charAt(cur) + 1));
                }

                else  {

                    while (cur-- > beg)  {
                        if (unqVal.charAt(cur) < '9')  {
                            unqVal.setCharAt(cur,
                                (char) (unqVal.charAt(cur) + 1));
                            break;
                        }
                    }

                    // See if there's a need to insert a new digit.
                    if (cur < beg)  {
                        unqVal.insert(++cur, '1');     end++;
                    }
                    while (cur < end)  {
                        unqVal.setCharAt(++cur, '0');
                    }

                }

            }

            return  unqVal.toString();

        }  /*  For  else  clause  of  selection-statement   If(!values ...   */

    }  /*  For  class  method   JavaUtils.getUniqueValue   */
}
