Package org.apache.axis.encoding

Source Code of org.apache.axis.encoding.TypeMappingImpl$Pair

/*
* The Apache Software License, Version 1.1
*
*
* Copyright (c) 2001 The Apache Software Foundation.  All rights
* reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* 1. Redistributions of source code must retain the above copyright
*    notice, this list of conditions and the following disclaimer.
*
* 2. Redistributions in binary form must reproduce the above copyright
*    notice, this list of conditions and the following disclaimer in
*    the documentation and/or other materials provided with the
*    distribution.
*
* 3. The end-user documentation included with the redistribution,
*    if any, must include the following acknowledgment:
*       "This product includes software developed by the
*        Apache Software Foundation (http://www.apache.org/)."
*    Alternately, this acknowledgment may appear in the software itself,
*    if and wherever such third-party acknowledgments normally appear.
*
* 4. The names "Axis" and "Apache Software Foundation" must
*    not be used to endorse or promote products derived from this
*    software without prior written permission. For written
*    permission, please contact apache@apache.org.
*
* 5. Products derived from this software may not be called "Apache",
*    nor may "Apache" appear in their name, without prior written
*    permission of the Apache Software Foundation.
*
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
* WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
* OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
* ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
* SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
* LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
* USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
* OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
* OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation.  For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*/

package org.apache.axis.encoding;

import org.apache.axis.Constants;
import org.apache.axis.encoding.ser.BeanSerializerFactory;
import org.apache.axis.encoding.ser.BeanDeserializerFactory;
import org.apache.axis.utils.JavaUtils;
import org.apache.axis.utils.ClassUtils;

import org.apache.axis.components.logger.LogFactory;
import org.apache.commons.logging.Log;

import javax.xml.namespace.QName;
import javax.xml.rpc.JAXRPCException;

import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;

/**
* @author Rich Scheuerle (scheu@us.ibm.com)
*
* This is the implementation of the axis TypeMapping interface (which extends
* the JAX-RPC TypeMapping interface).
*
* A TypeMapping is obtained from the singleton TypeMappingRegistry using
* the namespace of the webservice.  The TypeMapping contains the tuples
* {Java type, SerializerFactory, DeserializerFactory, Type QName)
*
* So if you have a Web Service with the namespace "XYZ", you call
* the TypeMappingRegistry.getTypeMapping("XYZ").
*
* The wsdl in your web service will use a number of types.  The tuple
* information for each of these will be accessed via the TypeMapping.
*
* Because every web service uses the soap, schema, wsdl primitives, we could
* pre-populate the TypeMapping with these standard tuples.  Instead,
* if the namespace/class matches is not found in the TypeMapping
* the request is delegated to the
* Default TypeMapping or another TypeMapping
*
*/
public class TypeMappingImpl implements TypeMapping
{
    protected static Log log =
        LogFactory.getLog(TypeMappingImpl.class.getName());

    public class Pair {
        public Class javaType;
        public QName xmlType;
        public Pair(Class javaType, QName xmlType) {
            this.javaType = javaType;
            this.xmlType = xmlType;
        }
        public boolean equals(Object o) {
            if (o == null) return false;
            Pair p = (Pair) o;
            // Test straight equality
            if (p.xmlType == this.xmlType &&
                p.javaType == this.javaType) {
                return true;
            }
            return (p.xmlType.equals(this.xmlType) &&
                    p.javaType.equals(this.javaType));
        }
        public int hashCode() {
            int hashcode = 0;
            if (javaType != null) {
                hashcode ^= javaType.hashCode();
            }
            if (xmlType != null) {
                hashcode ^= xmlType.hashCode();
            }
            return hashcode;
        }
    }

    private HashMap qName2Pair;     // QName to Pair Mapping
    private HashMap class2Pair;     // Class Name to Pair Mapping
    private HashMap pair2SF;        // Pair to Serialization Factory
    private HashMap pair2DF;        // Pair to Deserialization Factory
    protected TypeMapping delegate;   // Pointer to delegate or null
    private ArrayList namespaces;   // Supported namespaces

    /**
     * Should we "auto-type" classes we don't recognize into the "java:"
     * namespace?
     */
    private boolean doAutoTypes = false;

    /**
     * Construct TypeMapping
     */
    public TypeMappingImpl(TypeMapping delegate) {
        qName2Pair  = new HashMap();
        class2Pair  = new HashMap();
        pair2SF     = new HashMap();
        pair2DF     = new HashMap();
        this.delegate = delegate;
        namespaces  = new ArrayList();
    }

    /**
     * setDelegate sets the new Delegate TypeMapping
     */
    public void setDelegate(TypeMapping delegate) {
        this.delegate = delegate;
    }

    /**
     * getDelegate gets the new Delegate TypeMapping
     */
    public TypeMapping getDelegate() {
        return delegate;
    }

    /********* JAX-RPC Compliant Method Definitions *****************/

    /**
     * Gets the list of encoding styles supported by this TypeMapping object.
     *
     * @return  String[] of namespace URIs for the supported encoding
     * styles and XML schema namespaces.
     */
    public String[] getSupportedEncodings() {
        String[] stringArray = new String[namespaces.size()];
        return (String[]) namespaces.toArray(stringArray);
    }

    /**
     * Sets the list of encoding styles supported by this TypeMapping object.
     * (Not sure why this is useful...this information is automatically updated
     * during registration.
     *
     * @param namespaceURIs String[] of namespace URI's
     */
    public void setSupportedEncodings(String[] namespaceURIs) {
        namespaces.clear();
        for (int i =0; i< namespaceURIs.length; i++) {
            if (!namespaces.contains(namespaceURIs[i])) {
                namespaces.add(namespaceURIs[i]);
            }
        }
    }

    /**
     * isRegistered returns true if the [javaType, xmlType]
     * pair is registered.
     * @param javaType - Class of the Java type
     * @param xmlType - Qualified name of the XML data type
     * @return true if there is a mapping for the given pair, or
     * false if the pair is not specifically registered.
     *
     * For example if called with (java.lang.String[], soapenc:Array)
     * this routine will return false because this pair is
     * probably not specifically registered.
     * However if getSerializer is called with the same pair,
     * the default TypeMapping will use extra logic to find
     * a serializer (i.e. array serializer)
     */
    public boolean isRegistered(Class javaType, QName xmlType) {
        if (javaType == null || xmlType == null) {
            // REMOVED_FOR_TCK
            // return false;
            throw new JAXRPCException(
                    JavaUtils.getMessage(javaType == null ?
                                         "badJavaType" : "badXmlType"));
        }
        if (pair2SF.keySet().contains(new Pair(javaType, xmlType))) {
            return true;
        }
        if (delegate != null) {
            return delegate.isRegistered(javaType, xmlType);
        }
        return false;
    }

    /**
     * Registers SerializerFactory and DeserializerFactory for a
     * specific type mapping between an XML type and Java type.
     *
     * @param javaType - Class of the Java type
     * @param xmlType - Qualified name of the XML data type
     * @param sf - SerializerFactory
     * @param dsf - DeserializerFactory
     *
     * @throws JAXRPCException - If any error during the registration
     */
    public void register(Class javaType, QName xmlType,
                         javax.xml.rpc.encoding.SerializerFactory sf,
                         javax.xml.rpc.encoding.DeserializerFactory dsf)
        throws JAXRPCException {

        // Both javaType and xmlType must be specified.
        if (javaType == null || xmlType == null) {
            throw new JAXRPCException(
                    JavaUtils.getMessage(javaType == null ?
                                         "badJavaType" : "badXmlType"));
        }

        // At least a serializer or deserializer factory must be specified.
        if (sf == null && dsf == null) {
            throw new JAXRPCException(
                    JavaUtils.getMessage(sf == null ?
                                         "badSerFac" : "badDeserFac"));
        }

        //REMOVED_FOR_TCK
        //if (sf != null &&
        //    !(sf instanceof javax.xml.rpc.encoding.SerializerFactory)) {
        //    throw new JAXRPCException(message text);
        //}
        //if (dsf != null &&
        //    !(dsf instanceof javax.xml.rpc.encoding.DeserializerFactory)) {
        //    throw new JAXRPCException(message text);
        //}

        Pair pair = new Pair(javaType, xmlType);

        // Only register the appropriate mappings.
        if ((dsf != null) || (qName2Pair.get(xmlType) == null))
            qName2Pair.put(xmlType, pair);
        if ((sf != null) || (class2Pair.get(javaType) == null))
            class2Pair.put(javaType, pair);

        pair2SF.put(pair, sf);
        pair2DF.put(pair, dsf);
    }

    /**
     * Gets the SerializerFactory registered for the specified pair
     * of Java type and XML data type.
     *
     * @param javaType - Class of the Java type
     * @param xmlType - Qualified name of the XML data type
     *
     * @return Registered SerializerFactory
     *
     * @throws JAXRPCException - If there is no registered SerializerFactory
     * for this pair of Java type and XML data type
     * java.lang.IllegalArgumentException -
     * If invalid or unsupported XML/Java type is specified
     */
    public javax.xml.rpc.encoding.SerializerFactory
        getSerializer(Class javaType, QName xmlType)
        throws JAXRPCException {

        javax.xml.rpc.encoding.SerializerFactory sf = null;

        // If the xmlType was not provided, get one
        if (xmlType == null) {
            xmlType = getTypeQName(javaType);
            // If we couldn't find one, we're hosed, since getTypeQName()
            // already asked all of our delegates.
            if (xmlType == null) {
                return null;
            }

            // If we're doing autoTyping, and we got a type in the right
            // namespace, we can use the default serializer.
            if (doAutoTypes &&
                    xmlType.getNamespaceURI().equals(Constants.NS_URI_JAVA)) {
                return new BeanSerializerFactory(javaType, xmlType);
            }
        }

        // Try to get the serializer associated with this pair
        Pair pair = new Pair(javaType, xmlType);

        // Now get the serializer with the pair
        sf = (javax.xml.rpc.encoding.SerializerFactory) pair2SF.get(pair);

        // If not successful, use the javaType to get another Pair unless
        // we've got an array, in which case make sure we get the
        // ArraySerializer.
        if (sf == null) {
            if (javaType.isArray()) {
                pair = (Pair) qName2Pair.get(Constants.SOAP_ARRAY);
            } else {
                pair = (Pair) class2Pair.get(pair.javaType);
            }
            if (pair != null) {
                sf = (javax.xml.rpc.encoding.SerializerFactory) pair2SF.get(pair);
            }
        }

        if (sf == null && delegate != null) {
            sf = (SerializerFactory)
                delegate.getSerializer(javaType, xmlType);
        }
        return sf;
    }

    /**
     * Get the exact XML type QName which will be used when serializing a
     * given Class to a given type QName.  In other words, if we have:
     *
     * Class        TypeQName
     * ----------------------
     * Base         myNS:Base
     * Child        myNS:Child
     *
     * and call getXMLType(Child.class, BASE_QNAME), we should get
     * CHILD_QNAME.
     *
     * @param javaType
     * @param xmlType
     * @return the type's QName
     * @throws JAXRPCException
     */
    public QName getXMLType(Class javaType, QName xmlType)
        throws JAXRPCException
    {
        javax.xml.rpc.encoding.SerializerFactory sf = null;

        // If the xmlType was not provided, get one
        if (xmlType == null) {
            xmlType = getTypeQNameRecursive(javaType);

            // If we couldn't find one, we're hosed, since getTypeQName()
            // already asked all of our delegates.
            if (xmlType == null) {
                return null;
            }

            // If we're doing autoTyping, we can use the default.
            if (doAutoTypes &&
                    xmlType.getNamespaceURI().equals(Constants.NS_URI_JAVA)) {
                return xmlType;
            }
        }

        // Try to get the serializer associated with this pair
        Pair pair = new Pair(javaType, xmlType);

        // Now get the serializer with the pair
        sf = (javax.xml.rpc.encoding.SerializerFactory) pair2SF.get(pair);

        // If not successful, use the xmlType to get
        // another pair.  For some xmlTypes (like SOAP_ARRAY)
        // all of the possible javaTypes are not registered.
        if (sf == null) {
            if (javaType.isArray()) {
                pair = (Pair) qName2Pair.get(pair.xmlType);
            } else {
                pair = (Pair) class2Pair.get(pair.javaType);
            }
            if (pair != null) {
                sf = (javax.xml.rpc.encoding.SerializerFactory) pair2SF.get(pair);
            }
        }

        if (sf == null && delegate != null) {
            return ((TypeMappingImpl)delegate).getXMLType(javaType, xmlType);
        }

        if (pair != null) {
            xmlType = pair.xmlType;
        }

        return xmlType;
    }

    /**
     * Gets the DeserializerFactory registered for the specified pair
     * of Java type and XML data type.
     *
     * @param javaType - Class of the Java type
     * @param xmlType - Qualified name of the XML data type
     *
     * @return Registered DeserializerFactory
     *
     * @throws JAXRPCException - If there is no registered DeserializerFactory
     * for this pair of Java type and  XML data type
     * java.lang.IllegalArgumentException -
     * If invalid or unsupported XML/Java type is specified
     */
    public javax.xml.rpc.encoding.DeserializerFactory
        getDeserializer(Class javaType, QName xmlType)
        throws JAXRPCException {
        javax.xml.rpc.encoding.DeserializerFactory df = null;

        if (javaType == null) {
            javaType = getClassForQName(xmlType);
            // If we don't have a mapping, we're hosed since getClassForQName()
            // has already asked all our delegates.
            if (javaType == null) {
                return null;
            }

            if (doAutoTypes &&
                Constants.NS_URI_JAVA.equals(xmlType.getNamespaceURI())) {
                try {
                    javaType = ClassUtils.forName(xmlType.getLocalPart());
                } catch (ClassNotFoundException e) {
                    return null;
                }
                return new BeanDeserializerFactory(javaType, xmlType);
            }
        }

        Pair pair = new Pair(javaType, xmlType);

        df = (javax.xml.rpc.encoding.DeserializerFactory) pair2DF.get(pair);

        if (df == null && delegate != null) {
            df = (javax.xml.rpc.encoding.DeserializerFactory)
                delegate.getDeserializer(javaType, xmlType);
        }
        return df;
    }

    /**
     * Removes the SerializerFactory registered for the specified
     * pair of Java type and XML data type.
     *
     * @param javaType - Class of the Java type
     * @param xmlType - Qualified name of the XML data type
     *
     * @throws JAXRPCException - If there is error in
     * removing the registered SerializerFactory
     */
    public void removeSerializer(Class javaType, QName xmlType)
        throws JAXRPCException {
        if (javaType == null || xmlType == null) {
            throw new JAXRPCException(
                    JavaUtils.getMessage(javaType == null ?
                                         "badJavaType" : "badXmlType"));
        }

        Pair pair = new Pair(javaType, xmlType);
        pair2SF.remove(pair);
    }

    /**
     * Removes the DeserializerFactory registered for the specified
     * pair of Java type and XML data type.
     *
     * @param javaType - Class of the Java type
     * @param xmlType - Qualified name of the XML data type
     *
     * @throws JAXRPCException - If there is error in
     * removing the registered DeserializerFactory
     */
    public void removeDeserializer(Class javaType, QName xmlType)
        throws JAXRPCException {
        if (javaType == null || xmlType == null) {
            throw new JAXRPCException(
                    JavaUtils.getMessage(javaType == null ?
                                         "badJavaType" : "badXmlType"));
        }
        Pair pair = new Pair(javaType, xmlType);
        pair2DF.remove(pair);
    }


     /********* End JAX-RPC Compliant Method Definitions *****************/

    /**
     * Gets the QName for the type mapped to Class.
     * @param javaType class or type
     * @return xmlType qname or null
     */
    public QName getTypeQNameRecursive(Class javaType) {
        QName ret = null;
        while (javaType != null) {
            ret = getTypeQName(javaType);
            if (ret != null)
                return ret;

            // Walk my interfaces...
            Class [] interfaces = javaType.getInterfaces();
            if (interfaces != null) {
                for (int i = 0; i < interfaces.length; i++) {
                    Class iface = interfaces[i];
                    ret = getTypeQName(iface);
                    if (ret != null)
                        return ret;
                }
            }

            javaType = javaType.getSuperclass();
        }
        return null;
    }

    public QName getTypeQName(Class javaType) {
        //log.debug("getTypeQName javaType =" + javaType);
        if (javaType == null)
        return null;

        QName xmlType = null;
        Pair pair = (Pair) class2Pair.get(javaType);
        if (pair == null && delegate != null) {
            xmlType = delegate.getTypeQName(javaType);
        } else if (pair != null) {
            xmlType = pair.xmlType;
        }

        if (xmlType == null && doAutoTypes) {
            xmlType = new QName(Constants.NS_URI_JAVA,
                                javaType.getName());
        }

        // Can only detect arrays via code
        if (xmlType == null && (javaType.isArray() ||
             javaType == List.class ||
             List.class.isAssignableFrom(javaType))) {
            xmlType = Constants.SOAP_ARRAY;
        }

        //log.debug("getTypeQName xmlType =" + xmlType);
        return xmlType;
    }

    /**
     * Gets the Class mapped to QName.
     * @param xmlType qname or null
     * @return javaType class or type
     */
    public Class getClassForQName(QName xmlType) {
        //log.debug("getClassForQName xmlType =" + xmlType);
        Class javaType = null;
        Pair pair = (Pair) qName2Pair.get(xmlType);
        if (pair == null && delegate != null) {
            javaType = delegate.getClassForQName(xmlType);
        } else if (pair != null) {
            javaType = pair.javaType;
        }

        if (javaType == null && doAutoTypes &&
                Constants.NS_URI_JAVA.equals(xmlType.getNamespaceURI())) {
            // Classloader?
            try {
                javaType = ClassUtils.forName(xmlType.getLocalPart());
            } catch (ClassNotFoundException e) {
            }
        }

        //log.debug("getClassForQName javaType =" + javaType);
        return javaType;
    }

    /**
     * Gets the SerializerFactory registered for the Java type.
     *
     * @param javaType - Class of the Java type
     *
     * @return Registered SerializerFactory
     *
     * @throws JAXRPCException - If there is no registered SerializerFactory
     * for this pair of Java type and XML data type
     * java.lang.IllegalArgumentException -
     * If invalid or unsupported XML/Java type is specified
     */
    public javax.xml.rpc.encoding.SerializerFactory
        getSerializer(Class javaType)
        throws JAXRPCException
    {
        return getSerializer(javaType, null);
    }

    /**
     * Gets the DeserializerFactory registered for the xmlType.
     *
     * @param xmlType - Qualified name of the XML data type
     *
     * @return Registered DeserializerFactory
     *
     * @throws JAXRPCException - If there is no registered DeserializerFactory
     * for this pair of Java type and  XML data type
     * java.lang.IllegalArgumentException -
     * If invalid or unsupported XML/Java type is specified
     */
    public javax.xml.rpc.encoding.DeserializerFactory
        getDeserializer(QName xmlType)
        throws JAXRPCException {
        return getDeserializer(null, xmlType);
    }

    public void setDoAutoTypes(boolean doAutoTypes) {
        this.doAutoTypes = doAutoTypes;
    }
}
TOP

Related Classes of org.apache.axis.encoding.TypeMappingImpl$Pair

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.