public Object invoke()

in axis-rt-core/src/main/java/org/apache/axis/client/Call.java [2403:2603]


    public Object invoke( RPCElement body ) throws AxisFault {
        if (log.isDebugEnabled()) {
            log.debug("Enter: Call::invoke(RPCElement)");
        }

        /**
         * Since JAX-RPC requires us to specify a return type if we've set
         * parameter types, check for this case right now and toss a fault
         * if things don't look right.
         */
        if (!invokeOneWay && operation != null &&
                operation.getNumParams() > 0 && getReturnType() == null) {
            // TCK:
            // Issue an error if the return type was not set, but continue processing.
            //throw new AxisFault(Messages.getMessage("mustSpecifyReturnType"));
            log.error(Messages.getMessage("mustSpecifyReturnType"));
        }

        SOAPEnvelope         reqEnv =
                new SOAPEnvelope(msgContext.getSOAPConstants(),
                                 msgContext.getSchemaVersion());
        SOAPEnvelope         resEnv = null ;
        Message              reqMsg = new Message( reqEnv );
        Message              resMsg = null ;
        Vector               resArgs = null ;
        Object               result = null ;

        // Clear the output params
        outParams = new HashMap();
        outParamsList = new ArrayList();

        // Set both the envelope and the RPCElement encoding styles
        try {
            body.setEncodingStyle(getEncodingStyle());

            setRequestMessage(reqMsg);

            reqEnv.addBodyElement(body);
            reqEnv.setMessageType(Message.REQUEST);

            invoke();
        } catch (Exception e) {
            entLog.debug(Messages.getMessage("toAxisFault00"), e);
            throw AxisFault.makeFault(e);
        }

        resMsg = msgContext.getResponseMessage();

        if (resMsg == null) {
          if (msgContext.isPropertyTrue(FAULT_ON_NO_RESPONSE, false)) {
            throw new AxisFault(Messages.getMessage("nullResponse00"));
          } else {
            return null;
          }
        }

        resEnv = resMsg.getSOAPEnvelope();
        SOAPBodyElement bodyEl = resEnv.getFirstBody();
        if (bodyEl == null) {
            return null;
        }

        if (bodyEl instanceof RPCElement) {
            try {
                resArgs = ((RPCElement) bodyEl).getParams();
            } catch (Exception e) {
                log.error(Messages.getMessage("exception00"), e);
                throw AxisFault.makeFault(e);
            }

            if (resArgs != null && resArgs.size() > 0) {

                // If there is no return, then we start at index 0 to create the outParams Map.
                // If there IS a return, then we start with 1.
                int outParamStart = 0;

                // If we have resArgs and the returnType is specified, then the first
                // resArgs is the return.  If we have resArgs and neither returnType
                // nor paramXMLTypes are specified, then we assume that the caller is
                // following the non-JAX-RPC AXIS shortcut of not having to specify
                // the return, in which case we again assume the first resArgs is
                // the return.
                // NOTE 1:  the non-JAX-RPC AXIS shortcut allows a potential error
                // to escape notice.  If the caller IS NOT following the non-JAX-RPC
                // shortcut but instead intentionally leaves returnType and params
                // null (ie., a method that takes no parameters and returns nothing)
                // then, if we DO receive something it should be an error, but this
                // code passes it through.  The ideal solution here is to require
                // this caller to set the returnType to void, but there's no void
                // type in XML.
                // NOTE 2:  we should probably verify that the resArgs element
                // types match the expected returnType and paramXMLTypes, but I'm not
                // sure how to do that since the resArgs value is a Java Object
                // and the returnType and paramXMLTypes are QNames.

                // GD 03/15/02 : We're now checking for invalid metadata
                // config at the top of this method, so don't need to do it
                // here.  Check for void return, though.

                boolean findReturnParam = false;
                QName returnParamQName = null;
                if (operation != null) {
                    returnParamQName = operation.getReturnQName();
                }

                if (!XMLType.AXIS_VOID.equals(getReturnType())) {
                    if (returnParamQName == null) {
                        // Assume the first param is the return
                        RPCParam param = (RPCParam)resArgs.get(0);
                        result = param.getObjectValue();
                        outParamStart = 1;
                    } else {
                        // If the QName of the return value was given to us, look
                        // through the result arguments to find the right name
                        findReturnParam = true;
                    }
                }

                // The following loop looks at the resargs and
                // converts the value to the appropriate return/out parameter
                // value.  If the return value is found, is value is
                // placed in result.  The remaining resargs are
                // placed in the outParams list (note that if a resArg
                // is found that does not match a operation parameter qname,
                // it is still placed in the outParms list).
                for (int i = outParamStart; i < resArgs.size(); i++) {
                    RPCParam param = (RPCParam) resArgs.get(i);

                    Class javaType = getJavaTypeForQName(param.getQName());
                    Object value = param.getObjectValue();

                    // Convert type if needed
                    if (javaType != null && value != null &&
                           !javaType.isAssignableFrom(value.getClass())) {
                        value = JavaUtils.convert(value, javaType);
                    }

                    // Check if this parameter is our return
                    // otherwise just add it to our outputs
                    if (findReturnParam &&
                          returnParamQName.equals(param.getQName())) {
                        // found it!
                        result = value;
                        findReturnParam = false;
                    } else {
                        outParams.put(param.getQName(), value);
                        outParamsList.add(value);
                    }
                }

                // added by scheu:
                // If the return param is still not found, that means
                // the returned value did not have the expected qname.
                // The soap specification indicates that this should be
                // accepted (and we also fail interop tests if we are strict here).
                // Look through the outParms and find one that
                // does not match one of the operation parameters.
                if (findReturnParam) {
                    Iterator it = outParams.keySet().iterator();
                    while (findReturnParam && it.hasNext()) {
                        QName qname = (QName) it.next();
                        ParameterDesc paramDesc =
                            operation.getOutputParamByQName(qname);
                        if (paramDesc == null) {
                            // Doesn't match a paramter, so use this for the return
                            findReturnParam = false;
                            result = outParams.remove(qname);
                        }
                    }
                }

                // If we were looking for a particular QName for the return and
                // still didn't find it, throw an exception
                if (findReturnParam) {
                    String returnParamName = returnParamQName.toString();
                    throw new AxisFault(Messages.getMessage("noReturnParam",
                                                            returnParamName));
                }
            }
        } else {
            // This is a SOAPBodyElement, try to treat it like a return value
            try {
                result = bodyEl.getValueAsType(getReturnType());
            } catch (Exception e) {
                // just return the SOAPElement
                result = bodyEl;
            }

        }

        if (log.isDebugEnabled()) {
            log.debug("Exit: Call::invoke(RPCElement)");
        }

        // Convert type if needed
        if (operation != null && operation.getReturnClass() != null) {
            result = JavaUtils.convert(result, operation.getReturnClass());
        }

        return( result );
    }