Save This Page
Home » geronimo-2.2-source-release » org.apache.geronimo.axis.builder » [javadoc | source]
    1   /**
    2    *  Licensed to the Apache Software Foundation (ASF) under one or more
    3    *  contributor license agreements.  See the NOTICE file distributed with
    4    *  this work for additional information regarding copyright ownership.
    5    *  The ASF licenses this file to You under the Apache License, Version 2.0
    6    *  (the "License"); you may not use this file except in compliance with
    7    *  the License.  You may obtain a copy of the License at
    8    *
    9    *     http://www.apache.org/licenses/LICENSE-2.0
   10    *
   11    *  Unless required by applicable law or agreed to in writing, software
   12    *  distributed under the License is distributed on an "AS IS" BASIS,
   13    *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   14    *  See the License for the specific language governing permissions and
   15    *  limitations under the License.
   16    */
   17   package org.apache.geronimo.axis.builder;
   18   
   19   import java.lang.reflect.Method;
   20   import java.math.BigDecimal;
   21   import java.math.BigInteger;
   22   import java.net.URI;
   23   import java.util.ArrayList;
   24   import java.util.Calendar;
   25   import java.util.Collection;
   26   import java.util.Collections;
   27   import java.util.HashMap;
   28   import java.util.HashSet;
   29   import java.util.Iterator;
   30   import java.util.Map;
   31   import java.util.Set;
   32   
   33   import javax.wsdl.BindingInput;
   34   import javax.wsdl.BindingOperation;
   35   import javax.wsdl.Fault;
   36   import javax.wsdl.Message;
   37   import javax.wsdl.Part;
   38   import javax.wsdl.OperationType;
   39   import javax.wsdl.extensions.soap.SOAPBody;
   40   import javax.xml.namespace.QName;
   41   
   42   import org.apache.axis.constants.Style;
   43   import org.apache.axis.constants.Use;
   44   import org.apache.axis.description.FaultDesc;
   45   import org.apache.axis.description.OperationDesc;
   46   import org.apache.axis.description.ParameterDesc;
   47   import org.apache.axis.soap.SOAPConstants;
   48   import org.apache.axis.encoding.XMLType;
   49   import org.apache.geronimo.axis.client.OperationInfo;
   50   import org.apache.geronimo.common.DeploymentException;
   51   import org.apache.geronimo.kernel.ClassLoading;
   52   import org.apache.geronimo.xbeans.j2ee.ConstructorParameterOrderType;
   53   import org.apache.geronimo.xbeans.j2ee.ExceptionMappingType;
   54   import org.apache.geronimo.xbeans.j2ee.JavaWsdlMappingType;
   55   import org.apache.geronimo.xbeans.j2ee.MethodParamPartsMappingType;
   56   import org.apache.geronimo.xbeans.j2ee.ServiceEndpointMethodMappingType;
   57   import org.apache.geronimo.xbeans.j2ee.WsdlMessageMappingType;
   58   import org.apache.geronimo.xbeans.j2ee.WsdlReturnValueMappingType;
   59   import org.apache.xmlbeans.SchemaParticle;
   60   import org.apache.xmlbeans.SchemaProperty;
   61   import org.apache.xmlbeans.SchemaType;
   62   import org.objectweb.asm.Type;
   63   import org.apache.geronimo.xbeans.j2ee.JavaXmlTypeMappingType;
   64   import org.apache.geronimo.webservices.builder.SchemaInfoBuilder;
   65   import org.apache.geronimo.webservices.builder.WSDescriptorParser;
   66   
   67   /**
   68    * @version $Rev: 476049 $ $Date: 2006-11-16 20:35:17 -0800 (Thu, 16 Nov 2006) $
   69    */
   70   public class HeavyweightOperationDescBuilder extends OperationDescBuilder {
   71   
   72       private final JavaWsdlMappingType mapping;
   73       private final ServiceEndpointMethodMappingType methodMapping;
   74       private final SOAPBody soapBody;
   75   
   76   
   77       private final Map exceptionMap;
   78       private final SchemaInfoBuilder schemaInfoBuilder;
   79       private final ClassLoader classLoader;
   80       private final boolean rpcStyle;
   81       private final boolean documentStyle;
   82       private final boolean wrappedStyle;
   83       private final boolean isEncoded;
   84       private final Map publicTypes = new HashMap();
   85       private final Map anonymousTypes = new HashMap();
   86   
   87       /* Keep track of in and out parameter names so we can verify that
   88        * everything has been mapped and mapped correctly
   89        */
   90       private final Set inParamNames = new HashSet();
   91       private final Set outParamNames = new HashSet();
   92       private final Class serviceEndpointInterface;
   93   
   94       /**
   95        * Track the wrapper elements
   96        */
   97       private final Set wrapperElementQNames = new HashSet();
   98   
   99       public HeavyweightOperationDescBuilder(BindingOperation bindingOperation, JavaWsdlMappingType mapping, ServiceEndpointMethodMappingType methodMapping, Style defaultStyle, Map exceptionMap, SchemaInfoBuilder schemaInfoBuilder, JavaXmlTypeMappingType[] javaXmlTypeMappingTypes, ClassLoader classLoader, Class serviceEndpointInterface) throws DeploymentException {
  100           super(bindingOperation);
  101           this.mapping = mapping;
  102           this.methodMapping = methodMapping;
  103           this.exceptionMap = exceptionMap;
  104           this.schemaInfoBuilder = schemaInfoBuilder;
  105           for (int i = 0; i < javaXmlTypeMappingTypes.length; i++) {
  106               JavaXmlTypeMappingType javaXmlTypeMappingType = javaXmlTypeMappingTypes[i];
  107               String javaClassName = javaXmlTypeMappingType.getJavaType().getStringValue().trim();
  108               if (javaXmlTypeMappingType.isSetAnonymousTypeQname()) {
  109                   String anonymousTypeQName = javaXmlTypeMappingType.getAnonymousTypeQname().getStringValue().trim();
  110                   anonymousTypes.put(anonymousTypeQName, javaClassName);
  111               } else if (javaXmlTypeMappingType.isSetRootTypeQname()) {
  112                   QName qname = javaXmlTypeMappingType.getRootTypeQname().getQNameValue();
  113                   publicTypes.put(qname, javaClassName);
  114               }
  115           }
  116           this.classLoader = classLoader;
  117           this.serviceEndpointInterface = serviceEndpointInterface;
  118           BindingInput bindingInput = bindingOperation.getBindingInput();
  119           this.soapBody = (SOAPBody) SchemaInfoBuilder.getExtensibilityElement(SOAPBody.class, bindingInput.getExtensibilityElements());
  120   
  121           wrappedStyle = methodMapping.isSetWrappedElement();
  122           if (false == wrappedStyle) {
  123               Style style = Style.getStyle(soapOperation.getStyle(), defaultStyle);
  124               if (style == Style.RPC) {
  125                   rpcStyle = true;
  126                   documentStyle = false;
  127               } else {
  128                   rpcStyle = false;
  129                   documentStyle = true;
  130               }
  131           } else {
  132               rpcStyle = false;
  133               documentStyle = false;
  134           }
  135           isEncoded = Use.getUse(soapBody.getUse()) == Use.ENCODED;
  136       }
  137   
  138       public Set getWrapperElementQNames() throws DeploymentException {
  139           buildOperationDesc();
  140   
  141           return Collections.unmodifiableSet(wrapperElementQNames);
  142       }
  143   
  144       public boolean isEncoded() {
  145           return isEncoded;
  146       }
  147   
  148       public OperationInfo buildOperationInfo(SOAPConstants soapVersion) throws DeploymentException {
  149           buildOperationDesc();
  150   
  151           String soapActionURI = soapOperation.getSoapActionURI();
  152           boolean usesSOAPAction = (soapActionURI != null);
  153           QName operationQName = getOperationQName();
  154   
  155           String methodName = methodMapping.getJavaMethodName().getStringValue().trim();
  156   
  157           ArrayList parameters = operationDesc.getParameters();
  158           Type[] parameterASMTypes = new Type[parameters.size()];
  159           for (int i = 0; i < parameters.size(); i++) {
  160               ParameterDesc parameterDesc = (ParameterDesc) parameters.get(i);
  161               parameterASMTypes[i] = Type.getType(parameterDesc.getJavaType());
  162           }
  163   
  164           Type returnASMType = (operationDesc.getReturnClass() != null) ? Type.getType(operationDesc.getReturnClass()) : Type.VOID_TYPE;
  165   
  166           String methodDesc = Type.getMethodDescriptor(returnASMType, parameterASMTypes);
  167           OperationInfo operationInfo = new OperationInfo(operationDesc, usesSOAPAction, soapActionURI, soapVersion, operationQName, methodName, methodDesc);
  168           return operationInfo;
  169       }
  170   
  171       private QName getOperationQName() {
  172           if (wrappedStyle) {
  173               Map parts = operation.getInput().getMessage().getParts();
  174               if (parts != null && !parts.isEmpty()) {
  175                   for (Iterator iterator = parts.values().iterator(); iterator.hasNext();) {
  176                       Part part = (Part) iterator.next();
  177                       return part.getElementName();
  178                   }
  179               }
  180           }
  181           return getOperationNameFromSOAPBody();
  182   
  183       }
  184   
  185       public OperationDesc buildOperationDesc() throws DeploymentException {
  186           if (built) {
  187               return operationDesc;
  188           }
  189           built = true;
  190   
  191           operationDesc.setName(operationName);
  192   
  193           // Set to 'document', 'rpc' or 'wrapped'
  194           if (wrappedStyle) {
  195               operationDesc.setStyle(Style.WRAPPED);
  196           } else if (rpcStyle) {
  197               operationDesc.setStyle(Style.RPC);
  198           } else {
  199               operationDesc.setStyle(Style.DOCUMENT);
  200           }
  201   
  202           // Set to 'encoded' or 'literal'
  203           Use use = Use.getUse(soapBody.getUse());
  204           operationDesc.setUse(use);
  205   
  206   
  207           MethodParamPartsMappingType[] paramMappings = methodMapping.getMethodParamPartsMappingArray();
  208   
  209           /* Put the ParameterDesc instance in an array so they can be ordered properly
  210            * before they are added to the the OperationDesc.
  211            */
  212           ParameterDesc[] parameterDescriptions = new ParameterDesc[paramMappings.length];
  213   
  214   
  215           // MAP PARAMETERS
  216           for (int i = 0; i < paramMappings.length; i++) {
  217               MethodParamPartsMappingType paramMapping = paramMappings[i];
  218               int position = paramMapping.getParamPosition().getBigIntegerValue().intValue();
  219   
  220               ParameterDesc parameterDesc = mapParameter(paramMapping);
  221   
  222               parameterDescriptions[position] = parameterDesc;
  223           }
  224   
  225           if (wrappedStyle) {
  226               Part inputPart = getWrappedPart(input);
  227               QName name = inputPart.getElementName();
  228               SchemaType operationType = (SchemaType) schemaInfoBuilder.getComplexTypesInWsdl().get(name);
  229   
  230               Set expectedInParams = new HashSet();
  231   
  232               // schemaType should be complex using xsd:sequence compositor
  233               SchemaParticle parametersType = operationType.getContentModel();
  234               //parametersType can be null if the element has empty content such as
  235   //            <element name="getMarketSummary">
  236   //             <complexType>
  237   //              <sequence/>
  238   //             </complexType>
  239   //            </element>
  240   
  241               if (parametersType != null) {
  242                   if (SchemaParticle.ELEMENT == parametersType.getParticleType()) {
  243                       expectedInParams.add(parametersType.getName().getLocalPart());
  244                   } else if (SchemaParticle.SEQUENCE == parametersType.getParticleType()) {
  245                       SchemaParticle[] parameters = parametersType.getParticleChildren();
  246                       for (int i = 0; i < parameters.length; i++) {
  247                           expectedInParams.add(parameters[i].getName().getLocalPart());
  248                       }
  249                   }
  250               }
  251               if (!inParamNames.equals(expectedInParams)) {
  252                   throw new DeploymentException("Not all wrapper children were mapped for operation name" + operationName);
  253               }
  254           } else {
  255               //check that all input message parts are mapped
  256               if (!inParamNames.equals(input.getParts().keySet())) {
  257                   throw new DeploymentException("Not all input message parts were mapped for operation name" + operationName);
  258               }
  259           }
  260   
  261           Class[] paramTypes = new Class[parameterDescriptions.length];
  262           for (int i = 0; i < parameterDescriptions.length; i++) {
  263               ParameterDesc parameterDescription = parameterDescriptions[i];
  264               if (parameterDescription == null) {
  265                   throw new DeploymentException("There is no mapping for parameter number " + i + " for operation " + operationName);
  266               }
  267               operationDesc.addParameter(parameterDescription);
  268               paramTypes[i] = parameterDescription.getJavaType();
  269           }
  270   
  271           String methodName = methodMapping.getJavaMethodName().getStringValue().trim();
  272           Method method = null;
  273           try {
  274               method = serviceEndpointInterface.getMethod(methodName, paramTypes);
  275           } catch (NoSuchMethodException e) {
  276               String args = "(";
  277               for (int i = 0; i < paramTypes.length; i++) {
  278                   args += paramTypes[i].getName();
  279                   if (i < paramTypes.length - 1) {
  280                       args += ",";
  281                   }
  282               }
  283               args += ")";
  284   
  285               throw new DeploymentException("Mapping references non-existent method in service-endpoint: " + methodName + args);
  286           }
  287   
  288           operationDesc.setMethod(method);
  289   
  290           // MAP RETURN TYPE
  291           operationDesc.setMep(operation.getStyle());
  292           if (methodMapping.isSetWsdlReturnValueMapping()) {
  293               mapReturnType();
  294           } else if (operation.getStyle() == OperationType.REQUEST_RESPONSE) {
  295               //TODO WARNING THIS APPEARS TO SUBVERT THE COMMENT IN j2ee_jaxrpc_mapping_1_1.xsd IN service-endpoint-method-mappingType:
  296               //The wsdl-return-value-mapping is not specified for one-way operations.
  297               operationDesc.setReturnQName(null);             //??
  298               operationDesc.setReturnType(XMLType.AXIS_VOID);
  299               operationDesc.setReturnClass(void.class);
  300           }
  301   
  302           if (null != output && wrappedStyle) {
  303               Part inputPart = getWrappedPart(output);
  304               QName name = inputPart.getElementName();
  305               SchemaType operationType = (SchemaType) schemaInfoBuilder.getComplexTypesInWsdl().get(name);
  306   
  307               Set expectedOutParams = new HashSet();
  308   
  309               // schemaType should be complex using xsd:sequence compositor
  310               SchemaParticle parametersType = operationType.getContentModel();
  311               //again, no output can give null parametersType
  312               if (parametersType != null) {
  313                   if (SchemaParticle.ELEMENT == parametersType.getParticleType()) {
  314                       expectedOutParams.add(parametersType.getName().getLocalPart());
  315                   } else if (SchemaParticle.SEQUENCE == parametersType.getParticleType()) {
  316                       SchemaParticle[] parameters = parametersType.getParticleChildren();
  317                       for (int i = 0; i < parameters.length; i++) {
  318                           expectedOutParams.add(parameters[i].getName().getLocalPart());
  319                       }
  320                   }
  321               }
  322               if (!outParamNames.equals(expectedOutParams)) {
  323                   throw new DeploymentException("Not all wrapper children were mapped to parameters or a return value for operation " + operationName);
  324               }
  325           } else if (null != output) {
  326               if (!outParamNames.equals(output.getParts().keySet())) {
  327                   throw new DeploymentException("Not all output message parts were mapped to parameters or a return value for operation " + operationName);
  328               }
  329           }
  330   
  331           Map faultMap = operation.getFaults();
  332           for (Iterator iterator = faultMap.entrySet().iterator(); iterator.hasNext();) {
  333               Map.Entry entry = (Map.Entry) iterator.next();
  334               String faultName = (String) entry.getKey();
  335               Fault fault = (Fault) entry.getValue();
  336               FaultDesc faultDesc = mapException(faultName, fault);
  337   
  338               operationDesc.addFault(faultDesc);
  339           }
  340           return operationDesc;
  341       }
  342   
  343       //see jaxrpc 1.1 4.2.1
  344       private static final Map qnameToClassMap = new HashMap();
  345   
  346       static {
  347           qnameToClassMap.put(new QName("http://www.w3.org/2001/XMLSchema", "string"), String.class);
  348           qnameToClassMap.put(new QName("http://www.w3.org/2001/XMLSchema", "integer"), BigInteger.class);
  349           qnameToClassMap.put(new QName("http://www.w3.org/2001/XMLSchema", "int"), int.class);
  350           qnameToClassMap.put(new QName("http://www.w3.org/2001/XMLSchema", "long"), long.class);
  351           qnameToClassMap.put(new QName("http://www.w3.org/2001/XMLSchema", "short"), short.class);
  352           qnameToClassMap.put(new QName("http://www.w3.org/2001/XMLSchema", "decimal"), BigDecimal.class);
  353           qnameToClassMap.put(new QName("http://www.w3.org/2001/XMLSchema", "float"), float.class);
  354           qnameToClassMap.put(new QName("http://www.w3.org/2001/XMLSchema", "double"), double.class);
  355           qnameToClassMap.put(new QName("http://www.w3.org/2001/XMLSchema", "boolean"), boolean.class);
  356           qnameToClassMap.put(new QName("http://www.w3.org/2001/XMLSchema", "byte"), byte.class);
  357           qnameToClassMap.put(new QName("http://www.w3.org/2001/XMLSchema", "unsignedInt"), long.class);
  358           qnameToClassMap.put(new QName("http://www.w3.org/2001/XMLSchema", "unsignedShort"), int.class);
  359           qnameToClassMap.put(new QName("http://www.w3.org/2001/XMLSchema", "unsignedByte"), short.class);
  360           qnameToClassMap.put(new QName("http://www.w3.org/2001/XMLSchema", "QName"), QName.class);
  361           qnameToClassMap.put(new QName("http://www.w3.org/2001/XMLSchema", "dateTime"), Calendar.class);
  362           qnameToClassMap.put(new QName("http://www.w3.org/2001/XMLSchema", "date"), Calendar.class);
  363           qnameToClassMap.put(new QName("http://www.w3.org/2001/XMLSchema", "time"), Calendar.class);
  364           qnameToClassMap.put(new QName("http://www.w3.org/2001/XMLSchema", "anyURI"), URI.class);
  365           qnameToClassMap.put(new QName("http://www.w3.org/2001/XMLSchema", "base64Binary"), byte[].class);
  366           qnameToClassMap.put(new QName("http://www.w3.org/2001/XMLSchema", "hexBinary"), byte[].class);
  367           qnameToClassMap.put(new QName("http://www.w3.org/2001/XMLSchema", "anySimpleType"), String.class);
  368       }
  369   
  370   
  371       private FaultDesc mapException(String faultName, Fault fault) throws DeploymentException {
  372           Message message = fault.getMessage();
  373           QName messageQName = message.getQName();
  374           ExceptionMappingType exceptionMapping = (ExceptionMappingType) exceptionMap.get(messageQName);
  375           if (exceptionMapping == null) {
  376               throw new DeploymentException("No exception mapping for fault " + faultName + " and fault message " + messageQName + " for operation " + operationName);
  377           }
  378           String className = exceptionMapping.getExceptionType().getStringValue().trim();
  379           //TODO investigate whether there are other cases in which the namespace of faultQName can be determined.
  380           //this is weird, but I can't figure out what it should be.
  381           //if part has an element rather than a type, it should be part.getElementName() (see below)
  382           QName faultQName = new QName("", faultName);
  383           Part part;
  384           if (exceptionMapping.isSetWsdlMessagePartName()) {
  385               //According to schema documentation, this will only be set when several headerfaults use the same message.
  386               String headerFaultMessagePartName = exceptionMapping.getWsdlMessagePartName().getStringValue();
  387               part = message.getPart(headerFaultMessagePartName);
  388           } else {
  389               part = (Part) message.getOrderedParts(null).iterator().next();
  390           }
  391           QName faultTypeQName;// = part.getElementName() == null ? part.getTypeName() : part.getElementName();
  392           if (part.getElementName() == null) {
  393               faultTypeQName = part.getTypeName();
  394               if (faultTypeQName == null) {
  395                   throw new DeploymentException("Neither type nor element name supplied for part: " + part);
  396               }
  397           } else {
  398               faultQName = part.getElementName();
  399               faultTypeQName = (QName) schemaInfoBuilder.getElementToTypeMap().get(part.getElementName());
  400               if (faultTypeQName == null) {
  401                   throw new DeploymentException("Can not find type for: element: " + part.getElementName() + ", known elements: " + schemaInfoBuilder.getElementToTypeMap());
  402               }
  403           }
  404           SchemaType complexType = (SchemaType) schemaInfoBuilder.getComplexTypesInWsdl().get(faultTypeQName);
  405           boolean isComplex = complexType != null;
  406           FaultDesc faultDesc = new FaultDesc(faultQName, className, faultTypeQName, isComplex);
  407   
  408           //constructor parameters
  409           if (exceptionMapping.isSetConstructorParameterOrder()) {
  410               if (!isComplex) {
  411                   throw new DeploymentException("ConstructorParameterOrder can only be set for complex types, not " + faultTypeQName);
  412               }
  413               Map elementMap = new HashMap();
  414               SchemaProperty[] properties = complexType.getProperties();
  415               for (int i = 0; i < properties.length; i++) {
  416                   SchemaProperty property = properties[i];
  417                   QName elementName = property.getName();
  418                   SchemaType elementType = property.getType();
  419                   elementMap.put(elementName.getLocalPart(), elementType);
  420               }
  421               ArrayList parameterTypes = new ArrayList();
  422               ConstructorParameterOrderType constructorParameterOrder = exceptionMapping.getConstructorParameterOrder();
  423               for (int i = 0; i < constructorParameterOrder.getElementNameArray().length; i++) {
  424                   String elementName = constructorParameterOrder.getElementNameArray(i).getStringValue().trim();
  425                   SchemaType elementType = (SchemaType) elementMap.get(elementName);
  426                   Class javaElementType;
  427   
  428                   QName elementTypeQName = elementType.getName();
  429                   if (elementTypeQName != null) {
  430                       if (schemaInfoBuilder.getComplexTypesInWsdl().containsKey(elementType)) {
  431                           String javaClassName = (String) publicTypes.get(elementTypeQName);
  432                           if (javaClassName == null) {
  433                               throw new DeploymentException("No class mapped for element type: " + elementType);
  434                           }
  435                           javaElementType = getJavaClass(javaClassName);
  436                       } else {
  437                           javaElementType = (Class) qnameToClassMap.get(elementTypeQName);
  438                           if (javaElementType == null) {
  439                               throw new DeploymentException("Unknown type: " + elementType + " of name: " + elementName + " and QName: " + elementTypeQName);
  440                           }
  441                       }
  442                   } else {
  443                       //anonymous type
  444                       //anonymous type qname is constructed using rules 1.b and 2.b
  445                       String anonymousQName = complexType.getName().getNamespaceURI() + ":>" + complexType.getName().getLocalPart() + ">" + elementName;
  446                       String javaClassName = (String) anonymousTypes.get(anonymousQName);
  447                       if (javaClassName == null) {
  448                           if (elementType.isSimpleType()) {
  449                               //maybe it's a restriction of a built in simple type
  450                               SchemaType baseType = elementType.getBaseType();
  451                               QName simpleTypeQName = baseType.getName();
  452                               javaElementType = (Class) qnameToClassMap.get(simpleTypeQName);
  453                               if (javaElementType == null) {
  454                                   throw new DeploymentException("Unknown simple type: " + elementType + " of name: " + elementName + " and QName: " + simpleTypeQName);
  455                               }
  456                           } else {
  457                               throw new DeploymentException("No class mapped for anonymous type: " + anonymousQName);
  458                           }
  459                       } else {
  460                           javaElementType = getJavaClass(javaClassName);
  461                       }
  462                   }
  463                   //todo faultTypeQName is speculative
  464                   //todo outheader might be true!
  465                   ParameterDesc parameterDesc = new ParameterDesc(faultTypeQName, ParameterDesc.OUT, elementTypeQName, javaElementType, false, false);
  466                   parameterTypes.add(parameterDesc);
  467               }
  468               faultDesc.setParameters(parameterTypes);
  469           }
  470           return faultDesc;
  471       }
  472   
  473       private Class getJavaClass(String javaClassName) throws DeploymentException {
  474           try {
  475               Class javaClass = ClassLoading.loadClass(javaClassName, classLoader);
  476               return javaClass;
  477           } catch (ClassNotFoundException e) {
  478               throw new DeploymentException("Could not load class", e);
  479           }
  480       }
  481   
  482       private void mapReturnType() throws DeploymentException {
  483           QName returnType = null;
  484           QName returnQName = null;
  485           Class returnClass = null;
  486   
  487           if (output == null) {
  488               throw new DeploymentException("No output message, but a mapping for it for operation " + operationName);
  489           }
  490           WsdlReturnValueMappingType wsdlReturnValueMapping = methodMapping.getWsdlReturnValueMapping();
  491           String returnClassName = wsdlReturnValueMapping.getMethodReturnValue().getStringValue().trim();
  492           try {
  493               returnClass = ClassLoading.loadClass(returnClassName, classLoader);
  494           } catch (ClassNotFoundException e) {
  495               throw new DeploymentException("Could not load return type for operation " + operationName, e);
  496           }
  497   
  498           QName wsdlMessageQName = wsdlReturnValueMapping.getWsdlMessage().getQNameValue();
  499   
  500           if (!wsdlMessageQName.equals(output.getQName())) {
  501               throw new DeploymentException("OutputMessage has QName: " + output.getQName() + " but mapping specifies: " + wsdlMessageQName + " for operation " + operationName);
  502           }
  503   
  504           if (wsdlReturnValueMapping.isSetWsdlMessagePartName()) {
  505               String wsdlMessagePartName = wsdlReturnValueMapping.getWsdlMessagePartName().getStringValue().trim();
  506               if (outParamNames.contains(wsdlMessagePartName)) {
  507                   throw new DeploymentException("output message part " + wsdlMessagePartName + " has both an INOUT or OUT mapping and a return value mapping for operation " + operationName);
  508               }
  509   
  510               if (wrappedStyle) {
  511                   Part outPart = getWrappedPart(output);
  512                   SchemaParticle returnParticle = getWrapperChild(outPart, wsdlMessagePartName);
  513                   //TODO this makes little sense but may be correct, see comments in axis Parameter class
  514                   //the part name qname is really odd.
  515                   returnQName = new QName("", returnParticle.getName().getLocalPart());
  516                   returnType = returnParticle.getType().getName();
  517               } else if (rpcStyle) {
  518                   Part part = output.getPart(wsdlMessagePartName);
  519                   if (part == null) {
  520                       throw new DeploymentException("No part for wsdlMessagePartName " + wsdlMessagePartName + " in output message for operation " + operationName);
  521                   }
  522                   returnQName = new QName("", part.getName());
  523                   returnType = part.getTypeName();
  524               } else {
  525                   Part part = output.getPart(wsdlMessagePartName);
  526                   if (part == null) {
  527                       throw new DeploymentException("No part for wsdlMessagePartName " + wsdlMessagePartName + " in output message for operation " + operationName);
  528                   }
  529                   returnQName = getPartName(part);
  530                   returnType = returnQName;
  531               }
  532   
  533               outParamNames.add(wsdlMessagePartName);
  534           } else {
  535               //what does this mean????
  536           }
  537   
  538           operationDesc.setReturnQName(returnQName);
  539           operationDesc.setReturnType(returnType);
  540           operationDesc.setReturnClass(returnClass);
  541       }
  542   
  543       private ParameterDesc mapParameter(MethodParamPartsMappingType paramMapping) throws DeploymentException {
  544           WsdlMessageMappingType wsdlMessageMappingType = paramMapping.getWsdlMessageMapping();
  545           QName wsdlMessageQName = wsdlMessageMappingType.getWsdlMessage().getQNameValue();
  546           String wsdlMessagePartName = wsdlMessageMappingType.getWsdlMessagePartName().getStringValue().trim();
  547   
  548           String parameterMode = wsdlMessageMappingType.getParameterMode().getStringValue().trim();
  549           byte mode = ParameterDesc.modeFromString(parameterMode);
  550           boolean isInParam = mode == ParameterDesc.IN || mode == ParameterDesc.INOUT;
  551           boolean isOutParam = mode == ParameterDesc.OUT || mode == ParameterDesc.INOUT;
  552   
  553           if (isOutParam && output == null) {
  554               throw new DeploymentException("Mapping for output parameter " + wsdlMessagePartName + " found, but no output message for operation " + operationName);
  555           }
  556           boolean isSoapHeader = wsdlMessageMappingType.isSetSoapHeader();
  557           boolean inHeader = isSoapHeader && isInParam;
  558           boolean outHeader = isSoapHeader && isOutParam;
  559   
  560           QName paramQName;
  561           QName paramTypeQName;
  562   
  563           Part part = null;
  564           SchemaParticle inParameter = null;
  565           if (isInParam) {
  566               if (!wsdlMessageQName.equals(input.getQName())) {
  567                   throw new DeploymentException("QName of input message: " + input.getQName() +
  568                           " does not match mapping message QName: " + wsdlMessageQName + " for operation " + operationName);
  569               }
  570               if (wrappedStyle) {
  571                   Part inPart = getWrappedPart(input);
  572                   // the local name of the global element refered by the part is equal to the operation name
  573                   QName name = inPart.getElementName();
  574                   if (false == name.getLocalPart().equals(operationName)) {
  575                       throw new DeploymentException("message " + input.getQName() + " refers to a global element named " +
  576                               name.getLocalPart() + ", which is not equal to the operation name " + operationName);
  577                   }
  578                   inParameter = getWrapperChild(inPart, wsdlMessagePartName);
  579                   //TODO this makes little sense but may be correct, see comments in axis Parameter class
  580                   //the part name qname is really odd.
  581                   paramQName = new QName("", inParameter.getName().getLocalPart());
  582                   paramTypeQName = inParameter.getType().getName();
  583               } else if (rpcStyle) {
  584                   part = input.getPart(wsdlMessagePartName);
  585                   if (part == null) {
  586                       throw new DeploymentException("No part for wsdlMessagePartName " + wsdlMessagePartName + " in input message for operation " + operationName);
  587                   }
  588                   //TODO this makes little sense but may be correct, see comments in axis Parameter class
  589                   //the part name qname is really odd.
  590                   paramQName = new QName("", part.getName());
  591                   paramTypeQName = part.getTypeName();
  592               } else {
  593                   part = input.getPart(wsdlMessagePartName);
  594                   if (part == null) {
  595                       throw new DeploymentException("No part for wsdlMessagePartName " + wsdlMessagePartName + " in input message for operation " + operationName);
  596                   }
  597                   paramQName = getPartName(part);
  598                   paramTypeQName = paramQName;
  599               }
  600               inParamNames.add(wsdlMessagePartName);
  601               if (isOutParam) {
  602                   if (wrappedStyle) {
  603                       Part outPart = getWrappedPart(output);
  604                       SchemaParticle outParameter = getWrapperChild(outPart, wsdlMessagePartName);
  605                       if (inParameter.getType() != outParameter.getType()) {
  606                           throw new DeploymentException("The wrapper children " + wsdlMessagePartName +
  607                                   " do not have the same type for operation " + operationName);
  608                       }
  609                   } else if (rpcStyle) {
  610                       //inout, check that part of same name and type is in output message
  611                       Part outPart = output.getPart(wsdlMessagePartName);
  612                       if (outPart == null) {
  613                           throw new DeploymentException("No part for wsdlMessagePartName " + wsdlMessagePartName + " in output message for INOUT parameter of operation " + operationName);
  614                       }
  615                       // TODO this cannot happen.
  616                       if (!part.getName().equals(outPart.getName())) {
  617                           throw new DeploymentException("Mismatched input part name: " + part.getName() + " and output part name: " + outPart.getName() + " for INOUT parameter for wsdlMessagePartName " + wsdlMessagePartName + " for operation " + operationName);
  618                       }
  619                       if (!(part.getElementName() == null ? outPart.getElementName() == null : part.getElementName().equals(outPart.getElementName()))) {
  620                           throw new DeploymentException("Mismatched input part element name: " + part.getElementName() + " and output part element name: " + outPart.getElementName() + " for INOUT parameter for wsdlMessagePartName " + wsdlMessagePartName + " for operation " + operationName);
  621                       }
  622                       if (!(part.getTypeName() == null ? outPart.getTypeName() == null : part.getTypeName().equals(outPart.getTypeName()))) {
  623                           throw new DeploymentException("Mismatched input part type name: " + part.getTypeName() + " and output part type name: " + outPart.getTypeName() + " for INOUT parameter for wsdlMessagePartName " + wsdlMessagePartName + " for operation " + operationName);
  624                       }
  625                   } else {
  626                       part = output.getPart(wsdlMessagePartName);
  627                       if (part == null) {
  628                           throw new DeploymentException("No part for wsdlMessagePartName " + wsdlMessagePartName + " in output message for operation " + operationName);
  629                       }
  630                       paramQName = getPartName(part);
  631                       paramTypeQName = paramQName;
  632                   }
  633                   outParamNames.add(wsdlMessagePartName);
  634               }
  635           } else if (isOutParam) {
  636               if (!wsdlMessageQName.equals(output.getQName())) {
  637                   throw new DeploymentException("QName of output message: " + output.getQName() +
  638                           " does not match mapping message QName: " + wsdlMessageQName + " for operation " + operationName);
  639               }
  640               if (wrappedStyle) {
  641                   Part outPart = getWrappedPart(output);
  642                   SchemaParticle outParameter = getWrapperChild(outPart, wsdlMessagePartName);
  643                   //TODO this makes little sense but may be correct, see comments in axis Parameter class
  644                   //the part name qname is really odd.
  645                   paramQName = new QName("", outParameter.getName().getLocalPart());
  646                   paramTypeQName = outParameter.getType().getName();
  647               } else if (rpcStyle) {
  648                   part = output.getPart(wsdlMessagePartName);
  649                   if (part == null) {
  650                       throw new DeploymentException("No part for wsdlMessagePartName " + wsdlMessagePartName + " in output message for operation " + operationName);
  651                   }
  652                   //TODO this makes little sense but may be correct, see comments in axis Parameter class
  653                   //the part name qname is really odd.
  654                   paramQName = new QName("", part.getName());
  655                   paramTypeQName = part.getTypeName();
  656               } else {
  657                   part = output.getPart(wsdlMessagePartName);
  658                   if (part == null) {
  659                       throw new DeploymentException("No part for wsdlMessagePartName " + wsdlMessagePartName + " in output message for operation " + operationName);
  660                   }
  661                   paramQName = getPartName(part);
  662                   paramTypeQName = paramQName;
  663               }
  664               outParamNames.add(wsdlMessagePartName);
  665           } else {
  666               throw new AssertionError("a param mapping has to be IN or OUT or INOUT");
  667           }
  668   
  669           //use complexTypeMap
  670           boolean isComplexType = schemaInfoBuilder.getComplexTypesInWsdl().containsKey(paramTypeQName);
  671           String paramJavaTypeName = paramMapping.getParamType().getStringValue().trim();
  672           boolean isInOnly = mode == ParameterDesc.IN;
  673           Class actualParamJavaType = WSDescriptorParser.getHolderType(paramJavaTypeName, isInOnly, paramTypeQName, isComplexType, mapping, classLoader);
  674   
  675           ParameterDesc parameterDesc = new ParameterDesc(paramQName, mode, paramTypeQName, actualParamJavaType, inHeader, outHeader);
  676           return parameterDesc;
  677       }
  678   
  679       private QName getPartName(Part part) {
  680           return null == part.getElementName() ? part.getTypeName() : part.getElementName();
  681       }
  682   
  683       private Part getWrappedPart(Message message) throws DeploymentException {
  684           // in case of wrapped element, the message has only one part.
  685           Collection parts = message.getParts().values();
  686           if (1 != parts.size()) {
  687               throw new DeploymentException("message " + message.getQName() + " has " + parts.size() +
  688                       " parts and should only have one as wrapper style mapping is specified for operation " +
  689                       operationName);
  690           }
  691           return (Part) parts.iterator().next();
  692       }
  693   
  694       private SchemaParticle getWrapperChild(Part part, String wsdlMessagePartName) throws DeploymentException {
  695           QName name = part.getElementName();
  696   
  697           wrapperElementQNames.add(name);
  698   
  699           SchemaType operationType = (SchemaType) schemaInfoBuilder.getComplexTypesInWsdl().get(name);
  700           if (null == operationType) {
  701               throw new DeploymentException("No global element named " + name + " for operation " + operationName);
  702           }
  703   
  704           // schemaType should be complex using xsd:sequence compositor
  705           SchemaParticle parametersType = operationType.getContentModel();
  706           if (SchemaParticle.ELEMENT == parametersType.getParticleType()) {
  707               if (parametersType.getName().getLocalPart().equals(wsdlMessagePartName)) {
  708                   return parametersType;
  709               }
  710               throw new DeploymentException("Global element named " + name +
  711                       " does not define a child element named " + wsdlMessagePartName +
  712                       " required by the operation " + operationName);
  713           } else if (SchemaParticle.SEQUENCE == parametersType.getParticleType()) {
  714               SchemaParticle[] parameters = parametersType.getParticleChildren();
  715               for (int i = 0; i < parameters.length; i++) {
  716                   SchemaParticle parameter = parameters[i];
  717                   QName element = parameter.getName();
  718                   if (element.getLocalPart().equals(wsdlMessagePartName)) {
  719                       return parameter;
  720                   }
  721               }
  722               throw new DeploymentException("Global element named " + name +
  723                       " does not define a child element named " + wsdlMessagePartName +
  724                       " required by the operation " + operationName);
  725           } else {
  726               throw new DeploymentException("Global element named " + name +
  727                       " is not a sequence for operation " + operationName);
  728           }
  729       }
  730   
  731       /**
  732        * Supporting the Document/Literal Wrapped pattern
  733        *
  734        * See http://www-106.ibm.com/developerworks/webservices/library/ws-whichwsdl/ for a nice explanation and example
  735        *
  736        * wrapped-element tag is used
  737        * WSDL message with a single part
  738        * part uses the 'element' attribute to point to an elemement in the types section
  739        * the element type and the element's name match the operation name
  740        */
  741   }

Save This Page
Home » geronimo-2.2-source-release » org.apache.geronimo.axis.builder » [javadoc | source]