/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */

package org.apache.axis2.datasource.jaxb;

import org.apache.axiom.om.OMException;
import org.apache.axiom.om.impl.MTOMXMLStreamWriter;
import org.apache.axiom.om.util.XMLStreamWriterRemoveIllegalChars;
import org.apache.axiom.util.stax.XMLStreamReaderUtils;
import org.apache.axiom.util.stax.xop.XOPEncodedStream;
import org.apache.axiom.util.stax.xop.XOPUtils;
import org.apache.axis2.context.MessageContext;
import org.apache.axis2.java.security.AccessController;
import org.apache.axis2.jaxws.context.utils.ContextUtils;
import org.apache.axis2.jaxws.message.OccurrenceArray;
import org.apache.axis2.jaxws.message.databinding.JAXBUtils;
import org.apache.axis2.jaxws.message.util.XMLStreamWriterWithOS;
import org.apache.axis2.jaxws.spi.Constants;
import org.apache.axis2.jaxws.utility.JavaUtils;
import org.apache.axis2.jaxws.utility.XMLRootElementUtil;
import org.apache.axis2.jaxws.utility.XmlEnumUtils;
import org.apache.axis2.description.Parameter;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


import javax.xml.bind.JAXBContext;
import javax.xml.bind.JAXBElement;
import javax.xml.bind.JAXBException;
import javax.xml.bind.Marshaller;
import javax.xml.bind.PropertyException;
import javax.xml.bind.Unmarshaller;
import javax.xml.bind.attachment.AttachmentMarshaller;
import javax.xml.bind.attachment.AttachmentUnmarshaller;
import javax.xml.datatype.DatatypeConfigurationException;
import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.ws.Holder;
import javax.xml.ws.WebServiceException;
import java.io.OutputStream;
import java.lang.ref.WeakReference;
import java.lang.reflect.InvocationTargetException;
import java.security.PrivilegedAction;
import java.text.ParseException;
import java.util.HashMap;
import java.util.Map;
import java.util.TreeSet;

/*
 * To marshal or unmarshal a JAXB object, the JAXBContext is necessary.
 * In addition, access to the MessageContext and other context objects may be necessary
 * to get classloader information, store attachments etc.
 * 
 * The JAXBDSContext bundles all of this information together.
 */
public class JAXBDSContext {

    private static final Log log = LogFactory.getLog(JAXBDSContext.class);
    public static final boolean DEBUG_ENABLED = log.isDebugEnabled();

    private TreeSet<String> contextPackages;  // List of packages needed by the context
    private String contextPackagesKey;        // Unique key that represents the set of packages
    
    private JAXBContext customerJAXBContext;      // JAXBContext provided by the customer api
    //  JAXBContext loaded by the engine.  It is weakref'd to allow GC
    private WeakReference<JAXBContext> autoJAXBContext = null;   
    private JAXBUtils.CONSTRUCTION_TYPE       // How the JAXBContext is constructed
            constructionType = JAXBUtils.CONSTRUCTION_TYPE.UNKNOWN;
    private MessageContext msgContext;    

    // There are two modes of marshalling and unmarshalling: 
    //   "by java type" and "by schema element".
    // The prefered mode is "by schema element" because it is safe and xml-centric.
    // However there are some circumstances when "by schema element" is not available.
    //    Examples: RPC Lit processing (the wire element is defined by a wsdl:part...not schema)
    //              Doc/Lit Bare "Minimal" Processing (JAXB ObjectFactories are missing...
    //                   and thus we must use "by type" for primitives/String)
    // Please don't use "by java type" processing to get around errors.
    private Class<?> processType = null;
    private boolean isxmlList =false;
    
    private String webServiceNamespace;

    /**
     * Full Constructor JAXBDSContext (most performant)
     *
     * @param packages Set of packages needed by the JAXBContext.
     */
    public JAXBDSContext(TreeSet<String> packages, String packagesKey) {
        this.contextPackages = packages;
        this.contextPackagesKey = packagesKey;
    }

    /**
     * Slightly slower constructor
     *
     * @param packages
     */
    public JAXBDSContext(TreeSet<String> packages) {
        this(packages, packages.toString());
    }

    /**
     * Normal Constructor JAXBBlockContext
     *
     * @param contextPackage
     * @deprecated
     */
    public JAXBDSContext(String contextPackage) {
        this.contextPackages = new TreeSet<String>();
        this.contextPackages.add(contextPackage);
        this.contextPackagesKey = this.contextPackages.toString();
    }

    /**
     * "Dispatch" Constructor 
     * Use this full constructor when the JAXBContent is provided by the
     * customer.
     *
     * @param jaxbContext
     */
    public JAXBDSContext(JAXBContext jaxbContext) {
        this.customerJAXBContext = jaxbContext;
    }

    /** @return Class representing type of the element */
    public TreeSet<String> getContextPackages() {
        return contextPackages;
    }
    
    public JAXBContext getJAXBContext() throws JAXBException {
        
        return getJAXBContext(null);
    }

    /**
     * @return get the JAXBContext
     * @throws JAXBException
     */
    public JAXBContext getJAXBContext(ClassLoader cl) throws JAXBException {
        return getJAXBContext(cl, false);
    }
    
    /**
     * @param ClassLoader
     * @param forceArrays boolean (if true, then JAXBContext will automatically contain arrays)
     * @return get the JAXBContext
     * @throws JAXBException
     */
    public JAXBContext getJAXBContext(ClassLoader cl, boolean forceArrays) throws JAXBException {
        if (customerJAXBContext != null) {
            return customerJAXBContext;
        }
        
        // Get the weakly cached JAXBContext
        JAXBContext jc = null;
        if (autoJAXBContext != null) {
            jc = autoJAXBContext.get();
        }
        
        if (forceArrays && 
                jc != null &&
                constructionType != JAXBUtils.CONSTRUCTION_TYPE.BY_CLASS_ARRAY_PLUS_ARRAYS) {
            if (log.isDebugEnabled()) {
                log.debug("A JAXBContext exists but it was not constructed with array class.  " +
                    "The JAXBContext will be rebuilt.");
            }
            jc = null;
        }
        
        if (jc == null) {
            if (log.isDebugEnabled()) {
                log.debug("Creating a JAXBContext with the context packages.");
            }
            Holder<JAXBUtils.CONSTRUCTION_TYPE> constructType =
                    new Holder<JAXBUtils.CONSTRUCTION_TYPE>();
            Map<String, Object> properties = null;
            
            /*
             * We set the default namespace to the web service namespace to fix an
             * obscure bug.
             * 
             * If the class representing a JAXB data object does not define a namespace
             * (via an annotation like @XmlType or via ObjectFactory or schema gen information)
             * then the namespace information is defaulted.
             * 
             * The xjc tool defaults the namespace information to unqualified.
             * However the wsimport tool defaults the namespace to the namespace of the
             * webservice.
             * 
             * To "workaround" this issue, a default namespace equal to the webservice
             * namespace is set on the JAXB marshaller.  This has the effect of changing the
             * "unqualified namespaces" into the namespace used by the webservice.
             * 
             */
            if (this.webServiceNamespace != null) {
                properties = new HashMap<String, Object>();
                properties.put(JAXBUtils.DEFAULT_NAMESPACE_REMAP, this.webServiceNamespace);
            }
            jc = JAXBUtils.getJAXBContext(contextPackages, constructType, forceArrays,
                                          contextPackagesKey, cl, properties);
            constructionType = constructType.value;
            autoJAXBContext = new WeakReference<JAXBContext>(jc);
        } else {
            if (log.isDebugEnabled()) {
                log.debug("Using an existing JAXBContext");
            }
        }
        return jc;
    }

    public void setWebServiceNamespace(String namespace) {
        this.webServiceNamespace = namespace;
    }
    
    /** @return RPC Declared Type */
    public Class<?> getProcessType() {
        return processType;
    }

    /**
     * The procesess type to indicate the class of the target of the unmarshaling.
     * This method should only be used in the cases where the element being unmarshaled
     * is not known to the JAXBContext (examples include RPC/Literal processing
     * and Doc/Literal Wrapped processing with a non-element wrapper class)
     *
     * @param type
     */
    public void setProcessType(Class<?> type) {
    	if (log.isDebugEnabled()) {
     		log.debug("Process Type set to: " + type);
     	}
        processType = type;
    }

    public JAXBUtils.CONSTRUCTION_TYPE getConstructionType() {
        return constructionType;
    }

    public boolean isxmlList() {
        return isxmlList;
    }

    public void setIsxmlList(boolean isxmlList) {
    	if (log.isDebugEnabled()) {
     		log.debug("isxmlListSet to " + isxmlList);
     	}
        this.isxmlList = isxmlList;
    }
    
    public MessageContext getMessageContext() {
        return msgContext;
    }

    public void setMessageContext(MessageContext messageContext) {
        this.msgContext = messageContext;
    }
    
    public ClassLoader getClassLoader() {
        MessageContext context = getMessageContext();
        if (context != null) {
            Parameter param = context.getParameter(Constants.CACHE_CLASSLOADER);
            if (param != null) {
                return (ClassLoader) param.getValue();
            }
        }
        return null;
    }
    
    protected AttachmentContext createAttachmentContext() {
        return new MessageContextAttachmentContext(getMessageContext());
    }

    /**
     * Unmarshal the xml into a JAXB object
     * @param inputReader
     * @return
     * @throws JAXBException
     */
    public Object unmarshal(XMLStreamReader inputReader) throws JAXBException {

        if (DEBUG_ENABLED) {
            String clsText = (inputReader !=null) ? inputReader.getClass().toString() : "null";
            log.debug("unmarshal with inputReader=" + clsText);
        } 
        // See the Javadoc of the CustomBuilder interface for a complete explanation of
        // the following two instructions:
        XOPEncodedStream xopEncodedStream = XOPUtils.getXOPEncodedStream(inputReader);
        XMLStreamReader reader = XMLStreamReaderUtils.getOriginalXMLStreamReader(xopEncodedStream.getReader());
        if (DEBUG_ENABLED) {
            String clsText = (reader !=null) ? reader.getClass().toString() : "null";
            log.debug("  originalReader=" + clsText);
        } 
        
        // There may be a preferred classloader that should be used
        ClassLoader cl = getClassLoader();
        
        Unmarshaller u = JAXBUtils.getJAXBUnmarshaller(getJAXBContext(cl));

        
        // Create an attachment unmarshaller
        AttachmentUnmarshaller aum = new JAXBAttachmentUnmarshaller(createAttachmentContext(), xopEncodedStream.getMimePartProvider());

        if (aum != null) {
            if (DEBUG_ENABLED) {
                log.debug("Adding JAXBAttachmentUnmarshaller to Unmarshaller");
            } 
            u.setAttachmentUnmarshaller(aum);
        }

        Object jaxb = null;

        // Unmarshal into the business object.
        if (getProcessType() == null) {
            jaxb = unmarshalByElement(u, reader);   // preferred and always used for
                                                    // style=document
        } else {
            jaxb = unmarshalByType(u,
                                   reader,
                                   getProcessType(),
                                   isxmlList(),
                                   getConstructionType());
        }

        // Successfully unmarshalled the object
        JAXBUtils.releaseJAXBUnmarshaller(getJAXBContext(cl), u);
        
        // Don't close the reader.  The reader is owned by the caller, and it
        // may contain other xml instance data (other than this JAXB object)
        // reader.close();
        return jaxb;
    }
    
    /**
     * Marshal the jaxb object
     * @param obj
     * @param writer
     * @param am AttachmentMarshaller, optional Attachment
     */
    public void marshal(Object obj, 
            XMLStreamWriter writer) throws JAXBException {
        if (log.isDebugEnabled()) {
            log.debug("enter marshal");
        }
        boolean installedFilter = false;

        try {
            // There may be a preferred classloader that should be used
            ClassLoader cl = getClassLoader();


            // Very easy, use the Context to get the Marshaller.
            // Use the marshaller to write the object.
            JAXBContext jbc = getJAXBContext(cl);
            Marshaller m = JAXBUtils.getJAXBMarshaller(jbc);
            if (writer instanceof MTOMXMLStreamWriter && ((MTOMXMLStreamWriter) writer).getOutputFormat() != null) {
                String encoding = ((MTOMXMLStreamWriter) writer).getOutputFormat().getCharSetEncoding();

                String marshallerEncoding = (String) m.getProperty(Marshaller.JAXB_ENCODING);

                // Make sure that the marshaller respects the encoding of the message.
                // This is accomplished by setting the encoding on the Marshaller's JAXB_ENCODING property.
                if (encoding == null && marshallerEncoding == null) {
                    if (log.isDebugEnabled()) {
                        log.debug("The encoding and the marshaller's JAXB_ENCODING are both set to the default (UTF-8)");
                    }
                } else {
                    // Must set the encoding to an actual String to set it on the Marshaller
                    if (encoding == null) {
                        encoding = "UTF-8";
                    }
                    if (!encoding.equalsIgnoreCase(marshallerEncoding)) {
                        if (log.isDebugEnabled()) {
                            log.debug("The Marshaller.JAXB_ENCODING is " + marshallerEncoding);
                            log.debug("The Marshaller.JAXB_ENCODING is changed to the message encoding " + 
                                    encoding);
                        }
                        m.setProperty(Marshaller.JAXB_ENCODING, encoding);
                    } else {
                        if (log.isDebugEnabled()) {
                            log.debug("The encoding and the marshaller's JAXB_ENCODING are both set to:" + 
                                    marshallerEncoding);
                        }
                    }
                }
            }

            AttachmentMarshaller am = new JAXBAttachmentMarshaller(createAttachmentContext(), writer);
            if (am != null) {
                if (DEBUG_ENABLED) {
                    log.debug("Adding JAXBAttachmentMarshaller to Marshaller");
                }
                m.setAttachmentMarshaller(am);
            }

            MessageContext mc = getMessageContext();

            // If requested install a filter to remove illegal characters
            installedFilter = installFilter(mc, writer);


            // Marshal the object
            if (getProcessType() == null) {
                marshalByElement(obj, 
                        m, 
                        writer, 
                        true);
                //!am.isXOPPackage());
            } else {
                marshalByType(obj,
                        m,
                        writer,
                        getProcessType(),
                        isxmlList(),
                        getConstructionType(),
                        true); // Attempt to optimize by writing to OutputStream
            }

            JAXBUtils.releaseJAXBMarshaller(jbc, m);

            if (log.isDebugEnabled()) {
                log.debug("exit marshal");
            }
        } finally {
            // Make sure the filter is uninstalled
            if (installedFilter) {
                uninstallFilter(writer);
            }
        }
    }
    
    
    /**
     * Preferred way to marshal objects.
     * 
     * @param b Object that can be rendered as an element and the element name is known by the
     * Marshaller
     * @param m Marshaller
     * @param writer XMLStreamWriter
     */
    private static void marshalByElement(final Object b, final Marshaller m, 
                                         final XMLStreamWriter writer,
                                         final boolean optimize) {
        AccessController.doPrivileged(new PrivilegedAction<Void>() {
            public Void run() {
                // Marshalling directly to the output stream is faster than marshalling through the
                // XMLStreamWriter. 
                // Take advantage of this optimization if there is an output stream.
                try {
                    OutputStream os = (optimize) ? getOutputStream(writer,m) : null;
                    if (os != null) {
                        if (DEBUG_ENABLED) {
                            log.debug("Invoking marshalByElement.  " +
                                        "Marshaling to an OutputStream. " +
                                      "Object is "
                                      + getDebugName(b));
                        }
                        writer.flush();
                        m.marshal(b, os);
                    } else {
                        if (DEBUG_ENABLED) {
                            log.debug("Invoking marshalByElement.  " +
                                        "Marshaling to an XMLStreamWriter. " +
                                      "Object is "
                                      + getDebugName(b));
                        }
                        m.marshal(b, writer);
                    }
                } catch (OMException e) {
                    throw e;
                }
                catch (Throwable t) {
                    throw new OMException(t);
                }
                return null;
            }});
    }
    
    /**
     * Print out the name of the class of the specified object
     * @param o Object
     * @return text to use for debugging
     */
    private static String getDebugName(Object o) {
        String name = (o == null) ? "null" : o.getClass().getCanonicalName();
        if (o instanceof JAXBElement) {
            name += " containing " + getDebugName(((JAXBElement<?>) o).getValue());
        }
        return name;
    }

    /**
     * If the writer is backed by an OutputStream, then return the OutputStream
     * @param writer
     * @param Marshaller
     * @return OutputStream or null
     */
    private static OutputStream getOutputStream(XMLStreamWriter writer, 
                Marshaller m) throws XMLStreamException {
        if (log.isDebugEnabled()) {
            log.debug("XMLStreamWriter is " + writer);
        }
        OutputStream os = null;
        if (writer.getClass() == MTOMXMLStreamWriter.class) {
            os = ((MTOMXMLStreamWriter) writer).getOutputStream();
            if (log.isDebugEnabled()) {
                log.debug("OutputStream accessible from MTOMXMLStreamWriter is " + os);
            }
        }
        if (writer.getClass() == XMLStreamWriterWithOS.class) {
            os = ((XMLStreamWriterWithOS) writer).getOutputStream();
            if (log.isDebugEnabled()) {
                log.debug("OutputStream accessible from XMLStreamWriterWithOS is " + os);
            }
        }
        if (os != null) {
            String marshallerEncoding = null;
            try {
                marshallerEncoding = (String) m.getProperty(Marshaller.JAXB_ENCODING);
            } catch (PropertyException e) {
                if (DEBUG_ENABLED) {
                    log.debug("Could not query JAXB_ENCODING..Continuing. " + e);
                }
            }
            if (marshallerEncoding != null && !marshallerEncoding.equalsIgnoreCase("UTF-8")) {
                if (DEBUG_ENABLED) {
                    log.debug("Wrapping output stream to remove BOM");
                }
                os = new BOMOutputStreamFilter(marshallerEncoding, os);
            }
        }

        return os;
    }
    
    /**
     * The root element being read is defined by schema/JAXB; however its contents are known by
     * schema/JAXB. Therefore we use unmarshal by the declared type (This method is used to
     * unmarshal rpc elements)
     * 
     * @param u Unmarshaller
     * @param reader XMLStreamReader
     * @param type Class
     * @return Object
     * @throws WebServiceException
     */
    public static Object unmarshalByType(final Unmarshaller u, final XMLStreamReader reader,
                                          final Class<?> type, final boolean isList,
                                          final JAXBUtils.CONSTRUCTION_TYPE ctype)
        throws WebServiceException {

        if (DEBUG_ENABLED) {
            log.debug("Invoking unmarshalByType.");
            log.debug("  type = " + type);
            log.debug("  isList = " + isList);
            log.debug("  ctype = "+ ctype);
        }

        return AccessController.doPrivileged(new PrivilegedAction<Object>() {
            public Object run() {
                try {
                    // Unfortunately RPC is type based. Thus a
                    // declared type must be used to unmarshal the xml.
                    Object jaxb;
                   
                    if (!isList) {
                        // case: We are not unmarshalling an xsd:list but an Array.

                        if (type.isArray()) {
                            // If the context is created using package
                            // we will not have common arrays or type array in the context
                            // but there is not much we can do about it so seralize it as
                            // usual
                            if (ctype == JAXBUtils.CONSTRUCTION_TYPE.BY_CONTEXT_PATH) {
                                if (DEBUG_ENABLED) {
                                    log.debug("Unmarshal Array via BY_CONTEXT_PATH approach");
                                }
                                jaxb = u.unmarshal(reader, type);
                            }
                            // list on client array on server, Can happen only in start from java
                            // case.
                            else if ((ctype == JAXBUtils.CONSTRUCTION_TYPE.BY_CLASS_ARRAY)) {
                                // The type could be any Object or primitive
                            	
                            	//process primitives first
                            	//first verify if we have a primitive type associated in the array.
                            	//array could be single dimension or multi dimension.
                            	Class<?> cType = type.getComponentType();
                            	while(cType.isArray()){
                            		cType = cType.getComponentType();
                            	}
                            	if(cType.isPrimitive()){
                            	    if (DEBUG_ENABLED) {
                                        log.debug("Unmarshal Array of primitive via BY_CLASS_ARRAY approach");
                                    }
                            		jaxb = u.unmarshal(reader, type);
                            	}
                            	// process non primitive                       	
                                // I will first unmarshall the xmldata to a String[]
                                // Then use the unmarshalled jaxbElement to create
                                // proper type Object Array.
                            	
                            	else{
                            	    if (DEBUG_ENABLED) {
                                        log.debug("Unmarshal Array of non-primitive via BY_CLASS_ARRAY approach");
                                    }
                            		jaxb = unmarshalArray(reader, u, type);
                            	}
                                
                            } else {
                                if (DEBUG_ENABLED) {
                                    log.debug("Unmarshal Array");
                                }
                                jaxb = u.unmarshal(reader, type);
                                
                            }

                        } else if (type.isEnum()) {
                            // When JAXBContext is created using a context path, it will not 
                            // include Enum classes.
                            // These classes have @XmlEnum annotation but not @XmlType/@XmlElement,
                            // so the user will see MarshallingEx, class not known to ctxt.
                            // 
                            // This is a jax-b defect, for now this fix is in place to pass CTS.
                            // This only fixes the
                            // situation where the enum is the top-level object (e.g., message-part
                            // in rpc-lit scenario)
                            //
                            // Sample of what enum looks like:
                            // @XmlEnum public enum EnumString {
                            // @XmlEnumValue("String1") STRING_1("String1"),
                            // @XmlEnumValue("String2") STRING_2("String2");
                            //
                            // public static getValue(String){} <-- resolves a "value" to an emum
                            // object
                            // ... }
                            if (DEBUG_ENABLED) {
                                log.debug("Unmarshalling " + type.getName()
                                        + " as Enum");
                            }

                            JAXBElement<String> enumValue = u.unmarshal(reader, XmlEnumUtils.getConversionType(type));

                            if (enumValue != null) {
                                jaxb = XmlEnumUtils.fromValue(type, enumValue.getValue());
                            } else {
                                jaxb = null;
                            }
                        }
                        //Normal case: We are not unmarshalling a xsd:list or Array
                        else {
                            if (DEBUG_ENABLED) {
                                log.debug("Unmarshalling normal case (not array, not xsd:list, not enum)");
                            }
                            jaxb = u.unmarshal(reader, type);
                        }

                    } else {
                        // If this is an xsd:list, we need to return the appropriate
                        // list or array (see NOTE above)
                        // First unmarshal as a String
                        //Second convert the String into a list or array
                        if (DEBUG_ENABLED) {
                            log.debug("Unmarshalling xsd:list");
                        }
                        jaxb = unmarshalAsListOrArray(reader, u, type);
                        
                    }
                    if (log.isDebugEnabled()) {
                        if (jaxb == null) {
                            if (DEBUG_ENABLED) {
                                log.debug("End unmarshalByType returning null object");
                            }

                        } else if (jaxb instanceof JAXBElement) {
                            JAXBElement<?> jbe = (JAXBElement<?>) jaxb;
                            if (DEBUG_ENABLED) {
                                log.debug("End unmarshalByType returning JAXBElement");
                                log.debug("  Class = " + jbe.getDeclaredType());
                                log.debug("  QName = " + jbe.getName());
                            }
                        } else {
                            if (DEBUG_ENABLED) {
                                log.debug("End unmarshalByType returning " + jaxb.getClass());
                            }
                        }
                    }
                    return jaxb;
                } catch (OMException e) {
                    throw e;
                } catch (Throwable t) {
                    throw new OMException(t);
                }
            }
        });
    }

    private static Object unmarshalArray(final XMLStreamReader reader, 
                                         final Unmarshaller u, 
                                         Class<?> type)
       throws Exception {
        try {
            if (DEBUG_ENABLED) {
                log.debug("Invoking unmarshalArray");
            }
            Object jaxb = AccessController.doPrivileged(new PrivilegedAction<Object>() {
                public Object run() {
                    try {
                        return u.unmarshal(reader, String[].class);
                    } catch (OMException e) {
                        throw e;
                    } catch (Throwable t) {
                        throw new OMException(t);
                    }
                }
            });

            Object typeObj = getTypeEnabledObject(jaxb);

            // Now convert String Array in to the required Type Array.
            if (typeObj instanceof String[]) {
                String[] strArray = (String[]) typeObj;
                Object obj = XSDListUtils.fromStringArray(strArray, type);
                QName qName =
                    XMLRootElementUtil.getXmlRootElementQNameFromObject(jaxb);
                jaxb = new JAXBElement(qName, type, obj);
            }

            return jaxb;
        } catch (OMException e) {
            throw e;
        } catch (Throwable t) {
            throw new OMException(t);
        }
    }
   
    /**
     * convert the String into a list or array
     * @param <T>
     * @param jaxb
     * @param type
     * @return
     * @throws IllegalAccessException
     * @throws ParseException
     * @throws NoSuchMethodException
     * @throws InstantiationException
     * @throws DatatypeConfigurationException
     * @throws InvocationTargetException
     */
    public static Object unmarshalAsListOrArray(final XMLStreamReader reader, 
                                                final Unmarshaller u, 
                                                 Class<?> type)
        throws IllegalAccessException, ParseException,NoSuchMethodException,
        InstantiationException,
        DatatypeConfigurationException,InvocationTargetException,JAXBException {
        
        
            if (DEBUG_ENABLED) {
                log.debug("Invoking unmarshalAsListOrArray");
            }
            
            // If this is an xsd:list, we need to return the appropriate
            // list or array (see NOTE above)
            // First unmarshal as a String
            Object jaxb = null;
            try {
                jaxb = AccessController.doPrivileged(new PrivilegedAction<Object>() {
                    public Object run() {
                        try {
                            return u.unmarshal(reader, String.class);
                        } catch (OMException e) {
                            throw e;
                        } catch (Throwable t) {
                            throw new OMException(t);
                        }
                    }
                });
            } catch (OMException e) {
                throw e;
            } catch (Throwable t) {
                throw new OMException(t);
            }
            //Second convert the String into a list or array
            if (getTypeEnabledObject(jaxb) instanceof String) {
                QName qName = XMLRootElementUtil.getXmlRootElementQNameFromObject(jaxb);
                Object obj = XSDListUtils.fromXSDListString((String) getTypeEnabledObject(jaxb), type);
                return new JAXBElement(qName, type, obj);
            } else {
                return jaxb;
            }

    }

    /**
     * Return type enabled object
     *
     * @param obj type or element enabled object
     * @return type enabled object
     */
    static Object getTypeEnabledObject(Object obj) {
        if (obj == null) {
            return null;
        }
        if (obj instanceof JAXBElement) {
            return ((JAXBElement<?>) obj).getValue();
        }
        return obj;
    }

    private static boolean isOccurrenceArray(Object obj) {
        return (obj instanceof JAXBElement) &&
            (((JAXBElement<?>)obj).getValue() instanceof OccurrenceArray);
                
    }
    /**
     * Marshal objects by type
     * 
     * @param b Object that can be rendered as an element, but the element name is not known to the
     * schema (i.e. rpc)
     * @param m Marshaller
     * @param writer XMLStreamWriter
     * @param type Class
     * @param isList true if this is an XmlList
     * @param ctype CONSTRUCTION_TYPE
     * @param optimize boolean set to true if optimization directly to 
     * outputstream should be attempted.
     */
    private void marshalByType(final Object b, final Marshaller m,
                                      final XMLStreamWriter writer, final Class<?> type,
                                      final boolean isList, 
                                      final JAXBUtils.CONSTRUCTION_TYPE ctype,
                                      final boolean optimize) 
        throws WebServiceException {
        if (log.isDebugEnabled()) {
            log.debug("Enter marshalByType b=" + getDebugName(b) + 
                        " type=" + type + 
                        " marshaller=" + m +
                        " writer=" + writer +
                        " isList=" + isList +
                        " ctype=" + ctype +
                        " optimize=" + optimize);
                        
        }
        if (isOccurrenceArray(b)) {
            marshalOccurrenceArray((JAXBElement<?>) b, m, writer);
            return;
        }
        AccessController.doPrivileged(new PrivilegedAction<Void>() {
            public Void run() {
                try {

                    // NOTE
                    // Example:
                    // <xsd:simpleType name="LongList">
                    // <xsd:list>
                    // <xsd:simpleType>
                    // <xsd:restriction base="xsd:unsignedInt"/>
                    // </xsd:simpleType>
                    // </xsd:list>
                    // </xsd:simpleType>
                    // <element name="myLong" nillable="true" type="impl:LongList"/>
                    //
                    // LongList will be represented as an int[]
                    // On the wire myLong will be represented as a list of integers
                    // with intervening whitespace
                    // <myLong>1 2 3</myLong>
                    //
                    // Unfortunately, we are trying to marshal by type. Therefore
                    // we want to marshal an element (foo) that is unknown to schema.
                    // If we use the normal marshal code, the wire will look like
                    // this (which is incorrect):
                    // <foo><item>1</item><item>2</item><item>3</item></foo>
                    //
                    // The solution is to detect this situation and marshal the
                    // String instead. Then we get the correct wire format:
                    // <foo>1 2 3</foo>
                    Object jbo = b;
                    if(DEBUG_ENABLED){
                    	log.debug("check if marshalling list or array object, type = "+ (( b!=null )? b.getClass().getName():"null"));
                    }
                    if (isList) {                   	
                        if (DEBUG_ENABLED) {
                            log.debug("marshalling type which is a List");
                        }
                        
                        // This code assumes that the JAXBContext does not understand
                        // the array or list. In such cases, the contents are converted
                        // to a String and passed directly.
                        
                        if (ctype == JAXBUtils.CONSTRUCTION_TYPE.BY_CONTEXT_PATH) {
                            QName qName = XMLRootElementUtil.getXmlRootElementQNameFromObject(b);
                            String text = XSDListUtils.toXSDListString(getTypeEnabledObject(b));
                            if (DEBUG_ENABLED) {
                                log.debug("marshalling [context path approach] " +
                                                "with xmllist text = " + text);
                            }
                            jbo = new JAXBElement<String>(qName, String.class, text);
                        } else if (ctype == JAXBUtils.CONSTRUCTION_TYPE.BY_CLASS_ARRAY) {
                            // Some versions of JAXB have array/list processing built in.
                            // This code is a safeguard because apparently some versions
                            // of JAXB don't.
                            QName qName = XMLRootElementUtil.getXmlRootElementQNameFromObject(b);
                            String text = XSDListUtils.toXSDListString(getTypeEnabledObject(b));
                            if (DEBUG_ENABLED) {
                                log.debug("marshalling [class array approach] " +
                                                "with xmllist text = " + text);
                            }
                            jbo = new JAXBElement<String>(qName, String.class, text); 
                        }
                    }
                    // When JAXBContext is created using a context path, it will not include Enum
                    // classes.
                    // These classes have @XmlEnum annotation but not @XmlType/@XmlElement, so the
                    // user will see MarshallingEx, class not known to ctxt.
                    // 
                    // This is a jax-b defect, for now this fix is in place to pass CTS. This only
                    // fixes the
                    // situation where the enum is the top-level object (e.g., message-part in
                    // rpc-lit scenario)
                    //
                    // Sample of what enum looks like:
                    // @XmlEnum public enum EnumString {
                    // @XmlEnumValue("String1") STRING_1("String1"),
                    // @XmlEnumValue("String2") STRING_2("String2");
                    // ... }
                    if (type.isEnum()) {
                        if (b != null) {
                            if (DEBUG_ENABLED) {
                                log.debug("marshalByType. Marshaling " + type.getName()
                                        + " as Enum");
                            }
                            JAXBElement<?> jbe = (JAXBElement<?>) b;
                            String value = XMLRootElementUtil.getEnumValue((Enum<?>) jbe.getValue());

                            jbo = new JAXBElement<String>(jbe.getName(), String.class, value);
                        }
                    }

                    // If the output stream is available, marshal directly to it
                    OutputStream os = (optimize) ? getOutputStream(writer, m) : null;
                    if (os == null){ 
                        if (DEBUG_ENABLED) {
                            log.debug("Invoking marshalByType.  " +
                                    "Marshaling to an XMLStreamWriter. Object is "
                                    + getDebugName(jbo));
                        }   
                        m.marshal(jbo, writer);
                    } else {
                        if (DEBUG_ENABLED) {
                            log.debug("Invoking marshalByType.  " +
                                    "Marshaling to an OutputStream. Object is "
                                    + getDebugName(jbo));
                        }   
                        m.marshal(jbo, os);
                    }

                } catch (OMException e) {
                    throw e;
                } catch (Throwable t) {
                    throw new OMException(t);
                }
                return null;
            }
        });
    }

    /**
     * Marshal array objects by type
     * 
     * Invoke marshalByType for each element in the array
     * 
     * @param jaxb_in JAXBElement containing a value that is a List or array
     * @param m_in Marshaller
     * @param writer_in XMLStreamWriter
     */
    private void marshalOccurrenceArray(
                final JAXBElement<?> jbe_in, 
                final Marshaller m_in,
                final XMLStreamWriter writer_in) {
        
        if (log.isDebugEnabled()) {
            log.debug("Enter marshalOccurrenceArray");
            log.debug("  Marshaller = " + JavaUtils.getObjectIdentity(m_in));
        }
        
        AccessController.doPrivileged(new PrivilegedAction<Void>() {
            public Void run() {
                try {
                    
                    Marshaller m = m_in;
                    JAXBContext newJBC = null;
                    if (getConstructionType() != JAXBUtils.CONSTRUCTION_TYPE.BY_CLASS_ARRAY_PLUS_ARRAYS) {
                        // Rebuild JAXBContext
                        // There may be a preferred classloader that should be used
                        if (log.isDebugEnabled()) {
                            log.debug("Building a JAXBContext with array capability");
                        }
                        ClassLoader cl = getClassLoader();
                        newJBC = getJAXBContext(cl, true);
                        m = JAXBUtils.getJAXBMarshaller(newJBC);
                        if (log.isDebugEnabled()) {
                            log.debug("The new JAXBContext was constructed with " + getConstructionType());
                        }
                    }
                    

                    OccurrenceArray occurArray = (OccurrenceArray) jbe_in.getValue();

                    // Create a new JAXBElement.
                    // The name is the name of the individual occurence elements
                    // Type type is Object[]
                    // The value is the array of Object[] representing each element
                    JAXBElement<Object[]> jbe = new JAXBElement<Object[]>(jbe_in.getName(), 
                            Object[].class, 
                            occurArray.getAsArray());

                    // The jaxb marshal command cannot write out a list/array
                    // of occurence elements.  So we marshal it as a single
                    // element containing items...and then put a filter on the
                    // writer to transform it into a stream of occurence elements
                    XMLStreamWriterArrayFilter writer = new XMLStreamWriterArrayFilter(writer_in);


                    m.marshal(jbe, writer);
                    
                    if (newJBC != null) {
                        JAXBUtils.releaseJAXBMarshaller(newJBC, m);
                    }

                    return null;
                } catch (OMException e) {
                    throw e;
                } catch (Throwable t) {
                    throw new OMException(t);
                }
            }
            });
            
        
        if (log.isDebugEnabled()) {
            log.debug("Exit marshalOccurrenceArray");
        }
        
    }
    
    /**
     * Preferred way to unmarshal objects
     * 
     * @param u Unmarshaller
     * @param reader XMLStreamReader
     * @return Object that represents an element
     * @throws WebServiceException
     */
    public static Object unmarshalByElement(final Unmarshaller u, final XMLStreamReader reader)
        throws WebServiceException {
        try {
            if (DEBUG_ENABLED) {
                log.debug("Invoking unMarshalByElement");
            }
            return AccessController.doPrivileged(new PrivilegedAction<Object>() {
                public Object run() {
                    try {
                        return u.unmarshal(reader);
                    } catch (OMException e) {
                        throw e;
                    } catch (Throwable t) {
                        throw new OMException(t);
                    }
                }
            });

        } catch (OMException e) {
            throw e;
        } catch (Throwable t) {
            throw new OMException(t);
        }
    }
    

    /**
     * Install a JAXB filter if requested
     * @param mc
     * @param writer
     * @return true if filter installed
     */
    private boolean installFilter(MessageContext mc, XMLStreamWriter writer) {
        if (!(writer instanceof MTOMXMLStreamWriter)) {
            return false;
        }
        if (!ContextUtils.isJAXBRemoveIllegalChars(mc)) {
            return false;
        }
        
         
        MTOMXMLStreamWriter mtomWriter = (MTOMXMLStreamWriter) writer;
        mtomWriter.setFilter(new XMLStreamWriterRemoveIllegalChars());
        return true;
    }
    
    /**
     * UninstallInstall a JAXB filter if requested
     * @param mc
     * @param writer
     * @return true if filter installed
     */
    private void uninstallFilter(XMLStreamWriter writer) {
        MTOMXMLStreamWriter mtomWriter = (MTOMXMLStreamWriter) writer;
        mtomWriter.removeFilter();
    }

}
