jaxwsproxyhandler.java

来自「开源的axis2框架的源码。用于开发WEBSERVER」· Java 代码 · 共 443 行 · 第 1/2 页

JAVA
443
字号
/*
 * Licensed to the Apache Software Foundation (ASF) under one
 * or more contributor license agreements. See the NOTICE file
 * distributed with this work for additional information
 * regarding copyright ownership. The ASF licenses this file
 * to you under the Apache License, Version 2.0 (the
 * "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 *
 * http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing,
 * software distributed under the License is distributed on an
 * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
 * KIND, either express or implied. See the License for the
 * specific language governing permissions and limitations
 * under the License.
 */
package org.apache.axis2.jaxws.client.proxy;

import javax.xml.ws.handler.HandlerResolver;
import org.apache.axis2.jaxws.BindingProvider;
import org.apache.axis2.jaxws.ExceptionFactory;
import org.apache.axis2.jaxws.client.async.AsyncResponse;
import org.apache.axis2.jaxws.core.InvocationContext;
import org.apache.axis2.jaxws.core.InvocationContextFactory;
import org.apache.axis2.jaxws.core.MessageContext;
import org.apache.axis2.jaxws.core.controller.AxisInvocationController;
import org.apache.axis2.jaxws.core.controller.InvocationController;
import org.apache.axis2.jaxws.description.EndpointDescription;
import org.apache.axis2.jaxws.description.OperationDescription;
import org.apache.axis2.jaxws.description.ServiceDescription;
import org.apache.axis2.jaxws.i18n.Messages;
import org.apache.axis2.jaxws.marshaller.factory.MethodMarshallerFactory;
import org.apache.axis2.jaxws.message.Message;
import org.apache.axis2.jaxws.spi.Constants;
import org.apache.axis2.jaxws.spi.ServiceDelegate;
import org.apache.axis2.jaxws.spi.migrator.ApplicationContextMigratorUtil;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;

import javax.xml.ws.AsyncHandler;
import javax.xml.ws.Binding;
import javax.xml.ws.Response;
import javax.xml.ws.soap.SOAPBinding;
import java.lang.reflect.InvocationHandler;
import java.lang.reflect.Method;
import java.lang.reflect.Modifier;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;

/**
 * ProxyHandler is the java.lang.reflect.InvocationHandler implementation. When a JAX-WS client
 * calls the method on a proxy object, created by calling the ServiceDelegate.getPort(...) method,
 * the inovke method on the ProxyHandler is called.
 * <p/>
 * ProxyHandler uses EndpointInterfaceDescriptor and finds out if 1) The client call is Document
 * Literal or Rpc Literal 2) The WSDL is wrapped or unWrapped.
 * <p/>
 * ProxyHandler then reads OperationDescription using Method name called by Client From
 * OperationDescription it does the following 1) if the wsdl isWrapped() reads RequestWrapper Class
 * and responseWrapperClass 2) then reads the webParams for the Operation.
 * <p/>
 * isWrapped() = true  and DocLiteral then ProxyHandler then uses WrapperTool to create Request that
 * is a Wrapped JAXBObject. Creates JAXBBlock using JAXBBlockFactory Creates MessageContext->Message
 * and sets JAXBBlock to xmlPart as RequestMsgCtx in InvocationContext. Makes call to
 * InvocationController. Reads ResponseMsgCtx ->MessageCtx->Message->XMLPart. Converts that to
 * JAXBlock using JAXBBlockFactory and returns the BO from this JAXBBlock.
 * <p/>
 * isWrapped() != true and DocLiteral then ProxyHandler creates the JAXBBlock for the input request
 * creates a MessageContext that is then used by IbvocationController to invoke. Response is read
 * and return object is derived using @Webresult annotation. A JAXBBlock is created from the
 * Response and the BO from JAXBBlock is returned.
 */

public class JAXWSProxyHandler extends BindingProvider implements
        InvocationHandler {
    private static Log log = LogFactory.getLog(JAXWSProxyHandler.class);

    //Reference to ServiceDelegate instance that was used to create the Proxy
    protected ServiceDescription serviceDesc = null;

    private Class seiClazz = null;

    private Method method = null;

    public JAXWSProxyHandler(ServiceDelegate delegate, Class seiClazz, EndpointDescription epDesc) {
        super(delegate, epDesc);

        this.seiClazz = seiClazz;
        this.serviceDesc = delegate.getServiceDescription();
    }

    /* (non-Javadoc)
    * @see java.lang.reflect.InvocationHandler#invoke(java.lang.Object, java.lang.reflect.Method, java.lang.Object[])
    *
    * Invokes the method that was called on the java.lang.reflect.Proxy instance.
    */
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
        boolean debug = log.isDebugEnabled();
        if (debug) {
            log.debug("Attemping to invoke Method: " + method.getName());
        }

        this.method = method;

        if (!isValidMethodCall(method)) {
            throw ExceptionFactory.makeWebServiceException(
                    Messages.getMessage("proxyErr1", method.getName(), seiClazz.getName()));
        }

        if (!isPublic(method)) {
            throw ExceptionFactory.makeWebServiceException(
                    Messages.getMessage("proxyPrivateMethod", method.getName()));
        }

        if (isBindingProviderInvoked(method)) {
            // Since the JAX-WS proxy instance must also implement the javax.xml.ws.BindingProvider
            // interface, this object must handle those invocations as well.  In that case, we'll
            // delegate those calls to the BindingProvider object.
            if (debug) {
                log.debug(
                        "Invoking a public method on the javax.xml.ws.BindingProvider interface.");
            }
            try {
                return method.invoke(this, args);
            }
            catch (Throwable e) {
                if (debug) {
                    log.debug("An error occured while invoking the method: " + e.getMessage());
                }
                throw ExceptionFactory.makeWebServiceException(e);
            }
        } else {
            OperationDescription operationDesc =
                    endpointDesc.getEndpointInterfaceDescription().getOperation(method);
            if (isMethodExcluded(operationDesc)) {
                throw ExceptionFactory.makeWebServiceException(
                        Messages.getMessage("proxyExcludedMethod", method.getName()));
            }
            return invokeSEIMethod(method, args);
        }
    }

    /*
    * Performs the invocation of the method defined on the Service Endpoint
    * Interface.
    */
    private Object invokeSEIMethod(Method method, Object[] args) throws Throwable {
        if (log.isDebugEnabled()) {
            log.debug("Attempting to invoke SEI Method " + method.getName());
        }

        OperationDescription operationDesc =
                endpointDesc.getEndpointInterfaceDescription().getOperation(method);

        // Create and configure the request MessageContext
        InvocationContext requestIC = InvocationContextFactory.createInvocationContext(null);
        MessageContext request = createRequest(method, args);
        request.setEndpointDescription(getEndpointDescription());
        request.setOperationDescription(operationDesc);

        // Enable MTOM on the Message if the property was set on the SOAPBinding.
        Binding bnd = getBinding();
        if (bnd != null && bnd instanceof SOAPBinding) {
            if (((SOAPBinding)bnd).isMTOMEnabled()) {
                Message requestMsg = request.getMessage();
                requestMsg.setMTOMEnabled(true);
            }
        }
        
        /*
         * TODO: review: make sure the handlers are set on the InvocationContext
         * This implementation of the JAXWS runtime does not use Endpoint, which
         * would normally be the place to initialize and store the handler list.
         * In lieu of that, we will have to intialize and store them on the 
         * InvocationContext.  also see the InvocationContextFactory.  On the client
         * side, the binding is not yet set when we call into that factory, so the
         * handler list doesn't get set on the InvocationContext object there.  Thus
         * we gotta do it here.
         */
        
        // be sure to use whatever handlerresolver is registered on the Service
        requestIC.setHandlers(bnd.getHandlerChain());

        requestIC.setRequestMessageContext(request);
        requestIC.setServiceClient(serviceDelegate.getServiceClient(endpointDesc.getPortQName()));

        // TODO: Change this to some form of factory so that we can change the IC to
        // a more simple one for marshaller/unmarshaller testing.
        InvocationController controller = new AxisInvocationController();
        
        // Migrate the properties from the client request context bag to
        // the request MessageContext.
        ApplicationContextMigratorUtil.performMigrationToMessageContext(
                Constants.APPLICATION_CONTEXT_MIGRATOR_LIST_ID, 
                getRequestContext(), request);

        // Check if the call is OneWay, Async or Sync
        if (operationDesc.isOneWay()) {
            if (log.isDebugEnabled()) {
                log.debug("OneWay Call");
            }
            controller.invokeOneWay(requestIC);

            // Check to see if we need to maintain session state
            checkMaintainSessionState(request, requestIC);
        }

        if (method.getReturnType() == Future.class) {
            if (log.isDebugEnabled()) {
                log.debug("Async Callback");
            }

            //Get AsyncHandler from Objects and sent that to InvokeAsync
            AsyncHandler asyncHandler = null;
            for (Object obj : args) {
                if (obj != null && AsyncHandler.class.isAssignableFrom(obj.getClass())) {
                    asyncHandler = (AsyncHandler)obj;
                    break;
                }
            }

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?