📄 typemappingimpl.java
字号:
/* * 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.encoding;import org.apache.axis.Constants;import org.apache.axis.AxisProperties;import org.apache.axis.MessageContext;import org.apache.axis.AxisEngine;import org.apache.axis.handlers.soap.SOAPService;import org.apache.axis.components.logger.LogFactory;import org.apache.axis.encoding.ser.ArrayDeserializerFactory;import org.apache.axis.encoding.ser.ArraySerializerFactory;import org.apache.axis.encoding.ser.BeanDeserializerFactory;import org.apache.axis.encoding.ser.BeanSerializerFactory;import org.apache.axis.utils.ArrayUtil;import org.apache.axis.utils.Messages;import org.apache.axis.utils.ClassUtils;import org.apache.axis.utils.JavaUtils;import org.apache.axis.wsdl.toJava.Utils;import org.apache.axis.wsdl.fromJava.Namespaces;import org.apache.axis.wsdl.fromJava.Types;import org.apache.commons.logging.Log;import javax.xml.namespace.QName;import javax.xml.rpc.JAXRPCException;import java.lang.reflect.Array;import java.util.ArrayList;import java.util.HashMap;import java.util.List;import java.io.Serializable;/** * <p> * This is the implementation of the axis TypeMapping interface (which extends * the JAX-RPC TypeMapping interface). * </p> * <p> * 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) * </p> * <p> * So if you have a Web Service with the namespace "XYZ", you call * the TypeMappingRegistry.getTypeMapping("XYZ"). * </p> * <p> * 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. * </p> * <p> * 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 * </p> * * @author Rich Scheuerle (scheu@us.ibm.com) */public class TypeMappingImpl implements Serializable{ protected static Log log = LogFactory.getLog(TypeMappingImpl.class.getName()); /** * Work around a .NET bug with soap encoded types. * This is a static property of the type mapping that will * cause the class to ignore SOAPENC types when looking up * QNames of java types. See getTypeQNameExact(). */ public static boolean dotnet_soapenc_bugfix = false; public static class Pair implements Serializable { 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 private ArrayList namespaces; // Supported namespaces protected Boolean doAutoTypes = null; /** * Construct TypeMapping */ public TypeMappingImpl() { qName2Pair = new HashMap(); class2Pair = new HashMap(); pair2SF = new HashMap(); pair2DF = new HashMap(); namespaces = new ArrayList(); } private static boolean isArray(Class clazz) { return clazz.isArray() || java.util.Collection.class.isAssignableFrom(clazz); } /********* 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( Messages.getMessage(javaType == null ? "badJavaType" : "badXmlType")); } if (pair2SF.keySet().contains(new Pair(javaType, xmlType))) { return true; } 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 { // At least a serializer or deserializer factory must be specified. if (sf == null && dsf == null) { throw new JAXRPCException(Messages.getMessage("badSerFac")); } internalRegister(javaType, xmlType, sf, dsf); } /** * Internal version of register(), which allows null factories. * * @param javaType * @param xmlType * @param sf * @param dsf * @throws JAXRPCException */ protected void internalRegister(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( Messages.getMessage(javaType == null ? "badJavaType" : "badXmlType")); } //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); // This code used to not put the xmlType and the JavaType // in the maps if it already existed: // if ((dsf != null) || (qName2Pair.get(xmlType) == null)) // This goes against the philosphy that "last one registered wins". // In particular, the mapping for java.lang.Object --> anyType // was coming out in WSDL generation under the 1999 XML Schema // namespace, which .NET doesn't understand (and is not great anyway). qName2Pair.put(xmlType, pair); class2Pair.put(javaType, pair); if (sf != null) pair2SF.put(pair, sf); if (dsf != null) 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, null); // If we couldn't find one, we're hosed, since getTypeQName() // already asked all of our delegates. if (xmlType == null) { return null; } } // 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); // Need to look into hierarchy of component type. // ex) java.util.GregorianCalendar[] // -> java.util.Calendar[] if (sf == null && javaType.isArray()) { int dimension = 1; Class componentType = javaType.getComponentType(); while (componentType.isArray()) { dimension += 1; componentType = componentType.getComponentType(); } int[] dimensions = new int[dimension]; componentType = componentType.getSuperclass(); Class superJavaType = null; while (componentType != null) { superJavaType = Array.newInstance(componentType, dimensions).getClass(); pair = new Pair(superJavaType, xmlType); sf = (javax.xml.rpc.encoding.SerializerFactory) pair2SF.get(pair); if (sf != null) { break; } componentType = componentType.getSuperclass(); } } // check if ArrayOfT(xml)->T[](java) conversion is possible if (sf == null && javaType.isArray() && xmlType != null) { Pair pair2 = (Pair) qName2Pair.get(xmlType); if (pair2 != null && pair2.javaType != null && !pair2.javaType.isPrimitive() && ArrayUtil.isConvertable(pair2.javaType, javaType)) { sf = (javax.xml.rpc.encoding.SerializerFactory) pair2SF.get(pair2); } } // find serializer with xmlType if (sf == null && !javaType.isArray() && !Constants.isSchemaXSD(xmlType.getNamespaceURI()) && !Constants.isSOAP_ENC(xmlType.getNamespaceURI())) { Pair pair2 = (Pair) qName2Pair.get(xmlType); if (pair2 != null && pair2.javaType != null && !pair2.javaType.isArray() // for array && (javaType.isAssignableFrom(pair2.javaType) || (pair2.javaType.isPrimitive() && javaType == JavaUtils.getWrapperClass(pair2.javaType)))) // for derived type (xsd:restriction) { sf = (javax.xml.rpc.encoding.SerializerFactory) pair2SF.get(pair2); } } return sf; } public SerializerFactory finalGetSerializer(Class javaType) { Pair pair; if (isArray(javaType)) { pair = (Pair) qName2Pair.get(Constants.SOAP_ARRAY); } else { pair = (Pair) class2Pair.get(javaType); } if (pair != null) { return (SerializerFactory)pair2SF.get(pair); } return null; } /** * 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, boolean encoded)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -