FileDocCategorySizeDatePackage
RPCElement.javaAPI DocApache Axis 1.422040Sat Apr 22 18:57:28 BST 2006org.apache.axis.message

RPCElement

public class RPCElement extends SOAPBodyElement

Fields Summary
protected boolean
needDeser
org.apache.axis.description.OperationDesc[]
operations
Constructors Summary
public RPCElement(String namespace, String localName, String prefix, Attributes attributes, org.apache.axis.encoding.DeserializationContext context, org.apache.axis.description.OperationDesc[] operations)


      
                       
                       
                       
                       
                          
    
        super(namespace, localName, prefix, attributes, context);

        // This came from parsing XML, so we need to deserialize it sometime
        needDeser = true;

        // Obtain our possible operations
        if (operations == null) {
            updateOperationsByName();
        } else {
            this.operations = operations;
        }
    
public RPCElement(String namespace, String methodName, Object[] args)

        this.setNamespaceURI(namespace);
        this.name = methodName;

        for (int i = 0; args != null && i < args.length; i++) {
            if (args[i] instanceof RPCParam) {
                addParam((RPCParam)args[i]);
            } else {
                String name = null;
                if (name == null) name = "arg" + i;
                addParam(new RPCParam(namespace, name, args[i]));
            }
        }
    
public RPCElement(String methodName)

        this.name = methodName;
    
Methods Summary
public voidaddParam(RPCParam param)

        param.setRPCCall(this);
        initializeChildren();
        children.add(param);
    
public voiddeserialize()

        needDeser = false;

        MessageContext msgContext = context.getMessageContext();

        // Figure out if we should be looking for out params or in params
        // (i.e. is this message a response?)
        Message msg = msgContext.getCurrentMessage();
        SOAPConstants soapConstants = msgContext.getSOAPConstants();

        boolean isResponse = ((msg != null) &&
                              Message.RESPONSE.equals(msg.getMessageType()));

        // We're going to need this below, so create one.
        RPCHandler rpcHandler = new RPCHandler(this, isResponse);

        if (operations != null) {
            int numParams = (getChildren() == null) ? 0 : getChildren().size();

            SAXException savedException = null;

            // By default, accept missing parameters as nulls, and
            // allow the message context to override.
            boolean acceptMissingParams = msgContext.isPropertyTrue(
                    MessageContext.ACCEPTMISSINGPARAMS,
                    true);

            // We now have an array of all operations by this name.  Try to
            // find the right one.  For each matching operation which has an
            // equal number of "in" parameters, try deserializing.  If we
            // don't succeed for any of the candidates, punt.

            for (int i = 0; i < operations.length; i++) {
                OperationDesc operation = operations[i];

                // See if any information is coming from a header
                boolean needHeaderProcessing =
                    needHeaderProcessing(operation, isResponse);

                // Make a quick check to determine if the operation
                // could be a match.
                //  1) The element is the first param, DOCUMENT, (i.e.
                //     don't know the operation name or the number
                //     of params, so try all operations).
                //  or (2) Style is literal
                //     If the Style is LITERAL, the numParams may be inflated
                //     as in the following case:
                //     <getAttractions xmlns="urn:CityBBB">
                //         <attname>Christmas</attname>
                //         <attname>Xmas</attname>
                //     </getAttractions>
                //   for getAttractions(String[] attName)
                //   numParams will be 2 and and operation.getNumInParams=1
                //  or (3) Number of expected params is
                //         >= num params in message
                if (operation.getStyle() == Style.DOCUMENT ||
                    operation.getStyle() == Style.WRAPPED ||
                    operation.getUse() == Use.LITERAL ||
                    (acceptMissingParams ?
                        (operation.getNumInParams() >= numParams) :
                        (operation.getNumInParams() == numParams))) {

                    boolean isEncoded = operation.getUse() == Use.ENCODED;
                    rpcHandler.setOperation(operation);
                    try {
                        // If no operation name and more than one
                        // parameter is expected, don't
                        // wrap the rpcHandler in an EnvelopeHandler.
                         if ( ( msgContext.isClient() &&
                               operation.getStyle() == Style.DOCUMENT ) ||
                            ( !msgContext.isClient() &&
                               operation.getStyle() == Style.DOCUMENT &&
                               operation.getNumInParams() > 0 ) ) {                            context.pushElementHandler(rpcHandler);
                            context.setCurElement(null);
                        } else {
                            context.pushElementHandler(
                                    new EnvelopeHandler(rpcHandler));
                            context.setCurElement(this);
                        }

                        publishToHandler((org.xml.sax.ContentHandler) context);

                        // If parameter values are located in headers,
                        // get the information and publish the header
                        // elements to the rpc handler.
                        if (needHeaderProcessing) {
                            processHeaders(operation, isResponse,
                                           context, rpcHandler);
                        }

                        // Check if the RPCParam's value match the signature of the
                        // param in the operation.
                        boolean match = true;
                        List params = getParams2();
                        for ( int j = 0 ; j < params.size() && match ; j++ ) {
                            RPCParam rpcParam = (RPCParam)params.get(j);
                            Object value = rpcParam.getObjectValue();

                            // first check the type on the paramter
                            ParameterDesc paramDesc = rpcParam.getParamDesc();

                            // if we found some type info try to make sure the value type is
                            // correct.  For instance, if we deserialized a xsd:dateTime in
                            // to a Calendar and the service takes a Date, we need to convert
                            if (paramDesc != null && paramDesc.getJavaType() != null) {

                                // Get the type in the signature (java type or its holder)
                                Class sigType = paramDesc.getJavaType();

                                // if the type is an array but the value is not
                                // an array or Collection, put it into an
                                // ArrayList so that we correctly recognize it
                                // as convertible
                                if (sigType.isArray()) {
                                    if (value != null &&
                                            JavaUtils.isConvertable(value,
                                               sigType.getComponentType()) &&
                                          !(value.getClass().isArray()) &&
                                          !(value instanceof Collection)) {
                                        ArrayList list = new ArrayList();
                                        list.add(value);
                                        value = list;
                                        rpcParam.setObjectValue(value);
                                    }
                                }

                                if(!JavaUtils.isConvertable(value, sigType, isEncoded))
                                    match = false;
                            }
                        }
                        // This is not the right operation, try the next one.
                        if(!match) {
                            children = new ArrayList();
                            continue;
                        }

                        // Success!!  This is the right one...
                        msgContext.setOperation(operation);
                        return;
                    } catch (SAXException e) {
                        // If there was a problem, try the next one.
                        savedException = e;
                        children = new ArrayList();
                        continue;
                    }  catch (AxisFault e) {
                        // Thrown by getHeadersByName...
                        // If there was a problem, try the next one.
                        savedException = new SAXException(e);
                        children = new ArrayList();
                        continue;
                    }
                }
            }

            // If we're SOAP 1.2, getting to this point means bad arguments.
            if (!msgContext.isClient() && soapConstants == SOAPConstants.SOAP12_CONSTANTS) {
                AxisFault fault = new AxisFault(Constants.FAULT_SOAP12_SENDER, "string", null, null);
                fault.addFaultSubCode(Constants.FAULT_SUBCODE_BADARGS);
                throw new SAXException(fault);
            }

            if (savedException != null) {
                throw savedException;
            } else if (!msgContext.isClient()) {
                QName faultCode = new QName(Constants.FAULT_SERVER_USER);
                if (soapConstants == SOAPConstants.SOAP12_CONSTANTS)
                    faultCode = Constants.FAULT_SOAP12_SENDER;
                AxisFault fault = new AxisFault(faultCode,
                    null, Messages.getMessage("noSuchOperation", name), null, null, null);

                throw new SAXException(fault);
            }
        }

        if (operations != null) {
            rpcHandler.setOperation(operations[0]);
        }

        // Same logic as above.  Don't wrap rpcHandler
        // if there is no operation wrapper in the message
        if (operations != null && operations.length > 0 &&
            (operations[0].getStyle() == Style.DOCUMENT)) {
            context.pushElementHandler(rpcHandler);
            context.setCurElement(null);
        } else {
            context.pushElementHandler(new EnvelopeHandler(rpcHandler));
            context.setCurElement(this);
        }

        publishToHandler((org.xml.sax.ContentHandler)context);
    
public java.lang.StringgetMethodName()

        return name;
    
public org.apache.axis.description.OperationDesc[]getOperations()

        return this.operations;
    
public RPCParamgetParam(java.lang.String name)
This gets the FIRST param whose name matches. !!! Should it return more in the case of duplicates?

        if (needDeser) {
            deserialize();
        }

        List params = getParams2();
        for (int i = 0; i < params.size(); i++) {
            RPCParam param = (RPCParam)params.get(i);
            if (param.getName().equals(name))
                return param;
        }

        return null;
    
private java.util.ListgetParams(java.util.List list)

        for (int i = 0; children != null && i < children.size(); i++) {
            Object child = children.get(i);
            if (child instanceof RPCParam) {
                list.add(child);
            }
        }
        return list;
    
public java.util.VectorgetParams()

        if (needDeser) {
            deserialize();
        }
        
        return (Vector)getParams(new Vector());
    
private java.util.ListgetParams2()

        return getParams(new ArrayList());
    
private booleanneedHeaderProcessing(org.apache.axis.description.OperationDesc operation, boolean isResponse)
needHeaderProcessing

param
operation OperationDesc
param
isResponse boolean indicates if request or response message
return
true if the operation description indicates parameters/results are located in the soap header.


        // Search parameters/return to see if any indicate
        // that instance data is contained in the header.
        ArrayList paramDescs = operation.getParameters();
        if (paramDescs != null) {
            for (int j=0; j<paramDescs.size(); j++) {
                ParameterDesc paramDesc =
                    (ParameterDesc) paramDescs.get(j);
                if ((!isResponse && paramDesc.isInHeader()) ||
                    (isResponse && paramDesc.isOutHeader())) {
                    return true;
                }
            }
        }
        if (isResponse &&
            operation.getReturnParamDesc() != null &&
            operation.getReturnParamDesc().isOutHeader()) {
            return true;
        }
        return false;
    
protected voidoutputImpl(org.apache.axis.encoding.SerializationContext context)

        MessageContext msgContext = context.getMessageContext();
        boolean hasOperationElement =
            (msgContext == null  ||
             msgContext.getOperationStyle() == Style.RPC ||
             msgContext.getOperationStyle() == Style.WRAPPED);

        // When I have MIME and a no-param document WSDL, if I don't check
        // for no params here, the server chokes with "can't find Body".
        // because it will be looking for the enclosing element always
        // found in an RPC-style (and wrapped) request
        boolean noParams = getParams2().size() == 0;

        if (hasOperationElement || noParams) {
            // Set default namespace if appropriate (to avoid prefix mappings
            // in literal style).  Do this only if there is no encodingStyle.
            if (encodingStyle != null && encodingStyle.equals("")) {
                context.registerPrefixForURI("", getNamespaceURI());
            }
            context.startElement(new QName(getNamespaceURI(), name), attributes);
        }

        if(noParams) {
            if (children != null) {
                for (Iterator it = children.iterator(); it.hasNext();) {
                    ((NodeImpl)it.next()).output(context);
                }
            }
        } else {
            List params = getParams2();
            for (int i = 0; i < params.size(); i++) {
                RPCParam param = (RPCParam)params.get(i);
                if (!hasOperationElement && encodingStyle != null && encodingStyle.equals("")) {
                    context.registerPrefixForURI("", param.getQName().getNamespaceURI());
                }
                param.serialize(context);
            }
        }

        if (hasOperationElement || noParams) {
            context.endElement();
        }
    
private voidprocessHeaders(org.apache.axis.description.OperationDesc operation, boolean isResponse, org.apache.axis.encoding.DeserializationContext context, RPCHandler handler)
needHeaderProcessing

param
operation OperationDesc
param
isResponse boolean indicates if request or response message
param
context DeserializationContext
param
handler RPCHandler used to deserialize parameters are located in the soap header.

        // Inform handler that subsequent elements come from
        // the header
        try {
            handler.setHeaderElement(true);
            // Get the soap envelope
            SOAPElement envelope = getParentElement();
            while (envelope != null &&
                   !(envelope instanceof SOAPEnvelope)) {
                envelope = envelope.getParentElement();
            }
            if (envelope == null)
                return;

            // Find parameters that have instance
            // data in the header.
            ArrayList paramDescs = operation.getParameters();
            if (paramDescs != null) {
                for (int j=0; j<paramDescs.size(); j++) {
                    ParameterDesc paramDesc =
                        (ParameterDesc) paramDescs.get(j);
                    if ((!isResponse && paramDesc.isInHeader()) ||
                        (isResponse && paramDesc.isOutHeader())) {
                        // Get the headers that match the parameter's
                        // QName
                        Enumeration headers = ((SOAPEnvelope) envelope).
                            getHeadersByName(
                                 paramDesc.getQName().getNamespaceURI(),
                                 paramDesc.getQName().getLocalPart(),
                                 true);
                        // Publish each of the found elements to the
                        // handler.  The pushElementHandler and
                        // setCurElement calls are necessary to
                        // have the message element recognized as a
                        // child of the RPCElement.
                        while(headers != null &&
                              headers.hasMoreElements()) {
                            context.pushElementHandler(handler);
                            context.setCurElement(null);
                            ((MessageElement) headers.nextElement()).
                                publishToHandler(
                                   (org.xml.sax.ContentHandler)context);
                        }
                    }
                }
            }

            // Now do the same processing for the return parameter.
            if (isResponse &&
                operation.getReturnParamDesc() != null &&
                operation.getReturnParamDesc().isOutHeader()) {
                ParameterDesc paramDesc = operation.getReturnParamDesc();
                Enumeration headers =
                    ((SOAPEnvelope) envelope).
                    getHeadersByName(
                        paramDesc.getQName().getNamespaceURI(),
                        paramDesc.getQName().getLocalPart(),
                        true);
                while(headers != null &&
                      headers.hasMoreElements()) {
                    context.pushElementHandler(handler);
                    context.setCurElement(null);

                    ((MessageElement) headers.nextElement()).
                        publishToHandler((org.xml.sax.ContentHandler)context);
                }
            }
        } finally {
            handler.setHeaderElement(false);
        }
    
public voidsetNeedDeser(boolean needDeser)

        this.needDeser = needDeser;
    
public voidupdateOperationsByName()

        if (context == null) {
            return;
        }

        MessageContext msgContext = context.getMessageContext();

        if (msgContext == null) {
            return;
        }

        // Obtain our possible operations
        SOAPService service = msgContext.getService();
        if (service == null) {
            return;
        }

        ServiceDesc serviceDesc =
            service.getInitializedServiceDesc(msgContext);

        String lc = Utils.xmlNameToJava(name);
        if (serviceDesc == null) {
            throw AxisFault.makeFault(
                   new ClassNotFoundException(
                           Messages.getMessage("noClassForService00",
                                               lc)));
        }

        this.operations = serviceDesc.getOperationsByName(lc);
    
public voidupdateOperationsByQName()

        if (context == null) {
            return;
        }

        MessageContext msgContext = context.getMessageContext();

        if (msgContext == null) {
            return;
        }

        this.operations = msgContext.getPossibleOperationsByQName(getQName());