Package org.apache.axis.providers.java

Source Code of org.apache.axis.providers.java.RPCProvider

/*
* 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.providers.java ;

import org.apache.axis.AxisFault;
import org.apache.axis.Constants;
import org.apache.axis.MessageContext;
import org.apache.axis.description.OperationDesc;
import org.apache.axis.description.ServiceDesc;
import org.apache.axis.description.Parameter;
import org.apache.axis.handlers.soap.SOAPService;
import org.apache.axis.message.RPCElement;
import org.apache.axis.message.RPCParam;
import org.apache.axis.message.SOAPEnvelope;
import org.apache.axis.message.SOAPBodyElement;
import org.apache.axis.server.ParamList;
import org.apache.axis.utils.JavaUtils;
import org.apache.axis.utils.cache.JavaClass;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.xml.rpc.namespace.QName;
import java.lang.reflect.Method;
import java.lang.reflect.InvocationTargetException;
import java.util.StringTokenizer;
import java.util.Vector;
import java.util.Iterator;

/**
* Implement message processing by walking over RPCElements of the
* envelope body, invoking the appropriate methods on the service object.
*
* @author Doug Davis (dug@us.ibm.com)
*/
public class RPCProvider extends JavaProvider
{
    protected static Log log =
        LogFactory.getLog(RPCProvider.class.getName());

    public void processMessage (MessageContext msgContext,
                                String serviceName,
                                String allowedMethods,
                                SOAPEnvelope reqEnv,
                                SOAPEnvelope resEnv,
                                JavaClass jc,
                                Object obj)
        throws Exception
    {
        if (log.isDebugEnabled()) {
            log.debug(JavaUtils.getMessage("enter00",
                "RPCProvider.processMessage()"));
        }

        SOAPService service = msgContext.getService();
        ServiceDesc serviceDesc = service.getServiceDescription();
        OperationDesc operation = msgContext.getOperation();

        Vector          bodies = reqEnv.getBodyElements();
        if (log.isDebugEnabled()) {
            log.debug(JavaUtils.getMessage("bodyElems00", "" + bodies.size()));
            log.debug(JavaUtils.getMessage("bodyIs00", "" + bodies.get(0)));
        }

        /* Loop over each entry in the SOAPBody - each one is a different */
        /* RPC call.                                                      */
        /******************************************************************/
        for ( int bNum = 0 ; bNum < bodies.size() ; bNum++ ) {
            RPCElement   body;

            if (!(bodies.get(bNum) instanceof RPCElement)) {
                SOAPBodyElement bodyEl = (SOAPBodyElement)bodies.get(bNum);
                if (operation != null) {
                    Parameter param = operation.getParameter(bNum);
                    Object val = bodyEl.getValueAsType(param.getTypeQName());
                    body = new RPCElement("",
                                          operation.getName(),
                                          new Object [] { val });
                } else {
                    continue;
                }
            } else {
                body = (RPCElement) bodies.get( bNum );
            }

            String       mName      = body.getMethodName();
            Vector       args       = body.getParams();
            Object[]     argValues  =  null ;
           
           
            if ( args != null && args.size() > 0 ) {
                argValues = new Object[ args.size()];
                for ( int i = 0 ; i < args.size() ; i++ ) {
                    argValues[i= ((RPCParam)args.get(i)).getValue() ;
                   
                    if (log.isDebugEnabled()) {
                        log.debug("  " + JavaUtils.getMessage("value00",
                            "" + argValues[i]) );
                    }
                }
            }

            // Check if we can find a Method by this name
            checkMethodName(msgContext, allowedMethods, mName);

            // Get the actual method to invoke.
            // Since the method signature may contain output parameters
            // (Holders) there is no easy way to match the number of arguments
            // to a Method.  Furthermore method overloading does not work in
            // wsdl.  Thus the following code only works if there is no
            // overloading. 
            int  numberOfBodyArgs = args.size();
            Method[] methods = getMethod(msgContext, jc, mName);

            // If the method wasn't found, maybe it needs some Java mangling (ie., it's a Java
            // keyword or it's capitalized and the java mapping requires lowercase).
            if (methods == null) {
                mName = JavaUtils.xmlNameToJava(mName);
                methods = getMethod(msgContext, jc, mName);
            }

            if ( methods == null )
                throw new AxisFault( "AxisServer.error",
                        JavaUtils.getMessage("noMethod00", mName, msgContext.getTargetService()),
                        null, null );

            Object objRes = null;
            Class[] params = null;
            Exception ex = null;

            // There might be more than one method with this name, try them all.
            int index = 0;
            for (index = 0; index < methods.length; index++) {
                Method method = methods[index];
                ex = null;
                params = method.getParameterTypes();
               
                // Don't bother with this one if it has FEWER params
                if (argValues != null) {
                    if (params.length < argValues.length)
                        continue;
                }
               
                // The number of method parameters must match the
                // arguments taking into consideration output parameters.
                Object[] newArgValues = new Object[params.length];
                int old = 0;
                boolean problem = false;
                for (int n = 0; n < newArgValues.length; n++) {
                    Class heldType = JavaUtils.getHolderValueType(params[n]);
                    if (argValues != null && old < argValues.length) {
                        newArgValues[n] = argValues[old++];
                    } else if (heldType == null) {
                        // The parameters that don't match the argValues must
                        // be Holders.  Indicate problem occurred.
                        problem = true;
                    } else {
                        newArgValues[n] = null;
                    }
                    // Create holders for each argument that is null that should be a holder
                    if (newArgValues[n] == null && heldType != null) {
                        newArgValues[n] = JavaUtils.convert(newArgValues[n], params[n]);
                    }
                }
                if (!problem) {
                    argValues = newArgValues;  // Use newArgValues array if no problems
                }

                // Invoke the method and capture the returned object.
                // Note that if the method returns a primitive, invoke(...) automatically
                // wraps it in a java.lang class representing the primitive.
                try {
                    objRes = invokeMethod(msgContext, method, obj, argValues);
                    break;
                } catch (IllegalArgumentException e) {
                    // Hm - maybe we can help this with a conversion or two...
                    for (int i = 0; argValues != null && i < argValues.length &&
                      i < params.length; i++) {
                        Object thisArg = argValues[i];
                        if (!params[i].isAssignableFrom(thisArg.getClass())) {
                            // Attempt conversion for each non-assignable argument
                            Object newArg = JavaUtils.convert(thisArg, params[i]);
                            if (newArg != thisArg)
                                argValues[i] = newArg;
                        }
                    }

                    // OK, now try again...
                    try {
                        objRes = invokeMethod(msgContext, method, obj, argValues);
                        break;
                    } catch (IllegalArgumentException exp) {
                        StringBuffer argbuf = new StringBuffer();
                        String sep= "";
                        for(int i = 0; argValues != null &&
                          i < argValues.length; ++i) {
                            argbuf.append(sep);
                            sep = ", ";
                            argbuf.append(argValues[i] == null ? "null" : argValues[i].getClass().getName());
                        }
                        String objName = obj == null ? "null" :
                          obj.getClass().getName();
                        String msg = JavaUtils.getMessage("triedArgs00",
                                new String[] {
                                exp.getMessage(),
                                objName,
                                method.getName(),
                                argbuf.toString()});
                        ex = new IllegalArgumentException(msg);
                        continue;
                    }
                }
            }
            // If we've gone through all methods with the given name and there's
            // an exception left over, throw that exception.
            if (ex != null) {
                throw ex;
            }

            // If we've finished iterating through all the methods, throw an exception.
            if ( index == methods.length )
                throw new AxisFault( "AxisServer.error",
                        JavaUtils.getMessage("noMethod00", mName, msgContext.getTargetService()),
                        null, null );

            if (log.isDebugEnabled())
                log.debug(JavaUtils.getMessage("result00", "" + objRes));

            /* Now put the result in the result SOAPEnvelope */
            /*************************************************/
            RPCElement resBody = new RPCElement(mName + "Response");
            resBody.setPrefix( body.getPrefix() );
            resBody.setNamespaceURI( body.getNamespaceURI() );
            resBody.setEncodingStyle(msgContext.getEncodingStyle());

            if ( objRes != null ) {
                // In the old skeleton a param list was returned, which
                // contained the RPC params.  Preserve this for now.
                if (objRes instanceof ParamList) {
                    ParamList list = (ParamList)objRes;
                    for (int i = 0; i < list.size (); ++i) {
                        if (list.get (i) instanceof RPCParam) {
                            resBody.addParam ((RPCParam) list.get (i));
                        }
                        else {
                            resBody.addParam (new RPCParam (getParameterName(obj, methods[index],i, mName),
                                                            list.get (i)));
                        }
                    }
                }
                else {
                    QName returnQName = getReturnQName(serviceDesc, mName);
                    RPCParam param = new RPCParam(returnQName, objRes);
                    resBody.addParam(param);
                }
            } else if (methods[index].getReturnType() != Void.TYPE) {
                QName returnQName = getReturnQName(serviceDesc, mName);
                RPCParam param = new RPCParam(returnQName, objRes);
                resBody.addParam(param);
            }

            // The new skeleton (or no skeleton code) requires the runtime
            // to recognize holders and automatically pass back the outputs.
            for (int i=0; i < argValues.length; i++) {
                Class heldType = JavaUtils.getHolderValueType(params[i]);
                if (heldType != null) {
                    // Create an RPCParam by converting the Holder back into
                    // the held type.
                    resBody.addParam (new RPCParam (getParameterName(obj,
                                                                     methods[index],
                                                                     i,
                                                                     mName,
                                                                     args),
                                                    JavaUtils.convert(
                                                            argValues[i],
                                                            heldType)));
                }
            }
           
            resEnv.addBodyElement( resBody );
        }
    }
   
    protected Method[] getMethod(MessageContext msgContext, JavaClass jc, String mName)
        throws Exception
    {
        return jc.getMethod(mName);
    }

    protected Object invokeMethod(MessageContext msgContext,
                                  Method method, Object obj,
                                  Object[] argValues)
        throws Exception
    {
        return (method.invoke(obj, argValues));
    }

    protected void checkMethodName(MessageContext msgContext, String allowedMethods, String mName)
        throws Exception
    {
        String methodNameMatch = allowedMethods;

        // allowedMethods may be a comma-delimited string of method names.
        // If so, look for the one matching mname.
        if (allowedMethods != null && allowedMethods.indexOf(' ') != -1) {
            StringTokenizer tok = new StringTokenizer(allowedMethods, " ");
            String nextMethodName = null;
            while (tok.hasMoreElements()) {
                String token = tok.nextToken();
                if (token.equals(mName)) {
                    nextMethodName = token;
                    break;
                }
            }
            // didn't find a matching one...
            if (nextMethodName == null) {
                throw new AxisFault( "AxisServer.error",
                        JavaUtils.getMessage("namesDontMatch00", mName, allowedMethods),
                        null, null )// should they??
            }
            methodNameMatch = nextMethodName;
        }

        if ( methodNameMatch != null && !methodNameMatch.equals(mName) )
            throw new AxisFault( "AxisServer.error",
                    JavaUtils.getMessage("namesDontMatch01",
                        new String[] {mName, methodNameMatch, allowedMethods}),
                    null, null )// should they??

        if (log.isDebugEnabled()) {
            log.debug( "mName: " + mName );
            log.debug( "MethodNameMatch: " + methodNameMatch );
            log.debug( "MethodName List: " + allowedMethods );
        }

        ///////////////////////////////////////////////////////////////
        // If allowedMethods (i.e. methodNameMatch) is null,
        //  then treat it as a wildcard automatically matching mName
        ///////////////////////////////////////////////////////////////
        return;
    }

    /**
     * Returns or creates the parameter name for the i'th parm of
     * of the method specified.
     * (Use i=-1 to access the return name.)
     */
    protected QName getParameterName(Object obj,
                                      Method method,
                                      int i,
                                      String mName) {
        return getParameterName(obj, method, i, mName, null);
    }
   
    /**
     * Returns or creates the parameter name for the i'th parm of
     * of the method specified, using the name in the appropriate
     * position of the rpcParams Vector if it is supplied.
     *
     * (Use i=-1 to access the return name.)
     */
    protected QName getParameterName(Object obj,
                                      Method method,
                                      int i,
                                      String mName,
                                      Vector rpcParams) {
        QName parmName = null;
        // Emitter skeletons keep track of the parameter names
        if (obj instanceof org.apache.axis.wsdl.Skeleton)
            parmName = ((org.apache.axis.wsdl.Skeleton)obj).getParameterName(method.getName(), i);
        if (parmName == null) {
            if (i >= 0) {
                if (rpcParams != null && rpcParams.size() > i) {
                    parmName = ((RPCParam)rpcParams.get(i)).getQName();
                } else {
                    parmName = new QName("", mName + "Result" + i);
                }
            }
        }
        return parmName;
    }

    protected QName getReturnQName(ServiceDesc service, String methodName)
    {
        QName ret = null;

        if (service != null) {
            OperationDesc oper = service.getOperationDescByName(methodName);
            if (oper != null) {
                ret = oper.getReturnQName();
            }
        }

        if (ret == null) {
            ret = new QName("", methodName + "Result");
        }

        return ret;
    }
}
TOP

Related Classes of org.apache.axis.providers.java.RPCProvider

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.