Package org.apache.tuscany.sca.core.invocation.impl

Source Code of org.apache.tuscany.sca.core.invocation.impl.AsyncJDKInvocationHandler

/*
* 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.tuscany.sca.core.invocation.impl;

import java.beans.Introspector;
import java.beans.PropertyDescriptor;
import java.io.StringReader;
import java.lang.reflect.Method;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

import javax.xml.namespace.QName;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.transform.stream.StreamSource;
import javax.xml.ws.AsyncHandler;
import javax.xml.ws.Response;

import org.apache.tuscany.sca.assembly.AssemblyFactory;
import org.apache.tuscany.sca.assembly.Binding;
import org.apache.tuscany.sca.assembly.ComponentService;
import org.apache.tuscany.sca.assembly.Endpoint;
import org.apache.tuscany.sca.assembly.Implementation;
import org.apache.tuscany.sca.assembly.builder.BindingBuilder;
import org.apache.tuscany.sca.assembly.builder.BuilderContext;
import org.apache.tuscany.sca.assembly.builder.BuilderExtensionPoint;
import org.apache.tuscany.sca.assembly.xml.Constants;
import org.apache.tuscany.sca.context.CompositeContext;
import org.apache.tuscany.sca.contribution.processor.ContributionReadException;
import org.apache.tuscany.sca.contribution.processor.ProcessorContext;
import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessor;
import org.apache.tuscany.sca.contribution.processor.StAXArtifactProcessorExtensionPoint;
import org.apache.tuscany.sca.contribution.processor.ValidatingXMLInputFactory;
import org.apache.tuscany.sca.core.ExtensionPointRegistry;
import org.apache.tuscany.sca.core.FactoryExtensionPoint;
import org.apache.tuscany.sca.core.UtilityExtensionPoint;
import org.apache.tuscany.sca.core.assembly.RuntimeAssemblyFactory;
import org.apache.tuscany.sca.core.invocation.AsyncFaultWrapper;
import org.apache.tuscany.sca.core.invocation.AsyncResponseException;
import org.apache.tuscany.sca.core.invocation.AsyncResponseHandler;
import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException;
import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract;
import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory;
import org.apache.tuscany.sca.interfacedef.util.FaultException;
import org.apache.tuscany.sca.interfacedef.util.WrapperInfo;
import org.apache.tuscany.sca.invocation.InvocationChain;
import org.apache.tuscany.sca.invocation.MessageFactory;
import org.apache.tuscany.sca.policy.Intent;
import org.apache.tuscany.sca.provider.PolicyProvider;
import org.apache.tuscany.sca.provider.ServiceBindingProvider;
import org.apache.tuscany.sca.runtime.Invocable;
import org.apache.tuscany.sca.runtime.RuntimeComponent;
import org.apache.tuscany.sca.runtime.RuntimeEndpoint;
import org.apache.tuscany.sca.runtime.RuntimeEndpointReference;
import org.apache.tuscany.sca.work.WorkScheduler;
import org.oasisopen.sca.ServiceReference;
import org.oasisopen.sca.ServiceRuntimeException;

/**
* An InvocationHandler which deals with JAXWS-defined asynchronous client Java API method calls
*
* 2 asynchronous mappings exist for any given synchronous service operation, as shown in this example:
*  public interface StockQuote {
*      float getPrice(String ticker);
*      Response<Float> getPriceAsync(String ticker);
*      Future<?> getPriceAsync(String ticker, AsyncHandler<Float> handler);
*  }
*
* - the second method is called the "polling method", since the returned Response<?> object permits
*   the client to poll to see if the async call has completed
* - the third method is called the "async callback method", since in this case the client application can specify
*   a callback operation that is automatically called when the async call completes
*/
public class AsyncJDKInvocationHandler extends JDKInvocationHandler {

    private static final long serialVersionUID = 1L;

    private static int invocationCount = 10; // # of threads to use
    private static long maxWaitTime = 30; // Max wait time for completion = 30sec

    // Run the async service invocations using a ThreadPoolExecutor
    private ExecutorService theExecutor;

    public AsyncJDKInvocationHandler(ExtensionPointRegistry registry,
                                     MessageFactory messageFactory,
                                     ServiceReference<?> callableReference) {
        super(messageFactory, callableReference);
        initExecutorService(registry);
    }

    public AsyncJDKInvocationHandler(ExtensionPointRegistry registry,
                                     MessageFactory messageFactory,
                                     Class<?> businessInterface,
                                     Invocable source) {
        super(messageFactory, businessInterface, source);
        initExecutorService(registry);
    }

    private final void initExecutorService(ExtensionPointRegistry registry) {
        UtilityExtensionPoint utilities = registry.getExtensionPoint(UtilityExtensionPoint.class);
        WorkScheduler scheduler = utilities.getUtility(WorkScheduler.class);
        theExecutor = scheduler.getExecutorService();

        /*
        synchronized (AsyncJDKInvocationHandler.class) {
            theExecutor = utilities.getUtility(ExecutorService.class);
            if (theExecutor == null) {
                theExecutor =
                    new ThreadPoolExecutor(invocationCount, invocationCount, maxWaitTime, TimeUnit.SECONDS,
                                           new ArrayBlockingQueue<Runnable>(invocationCount));
                utilities.addUtility(ExecutorService.class, theExecutor);
            }
        }
        */
    }

    /**
     * Perform the invocation of the operation
     * - provides support for all 3 forms of client method: synchronous, polling and async callback
     */
    @Override
    public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {

        // force the bind of the reference so that we can look at the
        // target contract to see if it's asynchronous
        source.getInvocationChains();

        if (isAsyncCallback(method)) {
            return doInvokeAsyncCallback(proxy, method, args);
        } else if (isAsyncPoll(method)) {
            return doInvokeAsyncPoll(proxy, method, args);
        } else {
            // Regular synchronous method call
            return doInvokeSync(proxy, method, args);
        }
    }

    /**
     * Indicates if a supplied method has the form of an async callback method
     * @param method - the method
     * @return - true if the method has the form of an async callback
     */
    protected boolean isAsyncCallback(Method method) {
        if (method.getName().endsWith("Async") && (method.getReturnType() == Future.class)) {
            if (method.getParameterTypes().length > 0) {
                return method.getParameterTypes()[method.getParameterTypes().length - 1] == AsyncHandler.class;
            }
        }
        return false;
    }

    /**
     * Indicates is a supplied method has the form of an async polling method
     * @param method - the method
     * @return - true if the method has the form of an async polling method
     */
    protected boolean isAsyncPoll(Method method) {
        return method.getName().endsWith("Async") && (method.getReturnType() == Response.class);
    }

    /**
     * Invoke an async polling method
     * @param proxy - the reference proxy
     * @param asyncMethod - the async method to invoke
     * @param args - array of input arguments to the method
     * @return - the Response<?> object that is returned to the client application, typed by the
     *           type of the response
     */
    @SuppressWarnings("unchecked")
    protected Response doInvokeAsyncPoll(Object proxy, Method asyncMethod, Object[] args) {
        Method method = getNonAsyncMethod(asyncMethod);
        Class<?> returnType = method.getReturnType();
        // Allocate the Future<?> / Response<?> object - note: Response<?> is a subclass of Future<?>
        AsyncInvocationFutureImpl future = AsyncInvocationFutureImpl.newInstance(returnType, getInterfaceClassloader());
        try {
            invokeAsync(proxy, method, args, future, asyncMethod);
        } catch (Exception e) {
            future.setFault(new AsyncFaultWrapper(e));
        } catch (Throwable t) {
            Exception e =
                new ServiceRuntimeException("Received Throwable: " + t.getClass().getName()
                    + " when invoking: "
                    + asyncMethod.getName(), t);
            future.setFault(new AsyncFaultWrapper(e));
        } // end try
        return future;
    } // end method doInvokeAsyncPoll

    /**
     * Provide a synchronous invocation of a service operation that is either synchronous or asynchronous
     * @return
     */
    protected Object doInvokeSync(Object proxy, Method method, Object[] args) throws Throwable {
        if (isAsyncInvocation(source)) {
            // Target service is asynchronous
            Class<?> returnType = method.getReturnType();
            AsyncInvocationFutureImpl future =
                AsyncInvocationFutureImpl.newInstance(returnType, getInterfaceClassloader());
            invokeAsync(proxy, method, args, future, method);
            // Wait for some maximum time for the result - 1000 seconds here
            // Really, if the service is async, the client should use async client methods to invoke the service
            // - and be prepared to wait a *really* long time
            Object response = null;
            try {
                response = future.get(1000, TimeUnit.SECONDS);
            } catch (ExecutionException ex) {
                throw ex.getCause();
            }
            return response;
        } else {
            // Target service is not asynchronous, so perform sync invocation
            return super.invoke(proxy, method, args);
        } // end if
    } // end method doInvokeSync

    /**
     * Invoke an async callback method - note that this form of the async client API has as its final parameter
     * an AsyncHandler method, used for callbacks to the client code
     * @param proxy - the reference proxy
     * @param asyncMethod - the async method to invoke
     * @param args - array of input arguments to the method
     * @return - the Future<?> object that is returned to the client application, typed by the type of
     *           the response
     */
    @SuppressWarnings("unchecked")
    private Object doInvokeAsyncCallback(final Object proxy, final Method asyncMethod, final Object[] args)
        throws Exception {
        Future<Response> future = theExecutor.submit(new Callable<Response>() {

            @Override
            public Response call() {
                AsyncHandler handler = (AsyncHandler)args[args.length - 1];
                Response response = doInvokeAsyncPoll(proxy, asyncMethod, Arrays.copyOf(args, args.length - 1));
                // Invoke the callback handler, if present
                if (handler != null) {
                    handler.handleResponse(response);
                } // end if
                return response;
            }
        });
        return future.get();

    } // end method doInvokeAsyncCallback

    /**
     * Invoke the target (synchronous) method asynchronously
     * @param proxy - the reference proxy object
     * @param method - the method to invoke
     * @param args - arguments for the call
     * @param future - Future for handling the response
     * @return - returns the response from the invocation
     * @throws Throwable - if an exception is thrown during the invocation
     */
    @SuppressWarnings("unchecked")
    private void invokeAsync(Object proxy,
                             Method method,
                             Object[] args,
                             AsyncInvocationFutureImpl future,
                             Method asyncMethod) throws Throwable {
        if (source == null) {
            throw new ServiceRuntimeException("No runtime source is available");
        }

        if (source instanceof RuntimeEndpointReference) {
            RuntimeEndpointReference epr = (RuntimeEndpointReference)source;
            if (epr.isOutOfDate()) {
                epr.rebuild();
                chains.clear();
            }
        } // end if

        InvocationChain chain = getInvocationChain(method, source);

        if (chain == null) {
            throw new IllegalArgumentException("No matching operation is found: " + method);
        }

        // Organize for an async service
        RuntimeEndpoint theEndpoint = getAsyncCallback(source);
        boolean isAsyncService = false;
        if (theEndpoint != null) {
            // ... the service is asynchronous ...
            attachFuture(theEndpoint, future);
            isAsyncService = true;
        } else {
            // ... the service is synchronous ...
        } // end if

        // Perform the invocations on separate thread...
        theExecutor.submit(new separateThreadInvoker(chain, args, source, future, asyncMethod, isAsyncService));

        return;
    } // end method invokeAsync

    /**
     * An inner class which acts as a runnable task for invoking services asynchronously on threads that are separate from
     * those used to execute operations of components
     *
     * This supports both synchronous services and asynchronous services
     */
    private class separateThreadInvoker implements Runnable {

        private AsyncInvocationFutureImpl future;
        private Method asyncMethod;
        private InvocationChain chain;
        private Object[] args;
        private Invocable invocable;
        private boolean isAsyncService;

        public separateThreadInvoker(InvocationChain chain,
                                     Object[] args,
                                     Invocable invocable,
                                     AsyncInvocationFutureImpl future,
                                     Method asyncMethod,
                                     boolean isAsyncService) {
            super();
            this.chain = chain;
            this.asyncMethod = asyncMethod;
            this.args = args;
            this.invocable = invocable;
            this.future = future;
            this.isAsyncService = isAsyncService;
        } // end constructor

        public void run() {
            Object result;

            try {
                if (isAsyncService) {
                    invoke(chain, args, invocable, future.getUniqueID());
                    // The result is returned asynchronously via the future...
                } else {
                    // ... the service is synchronous ...
                    result = invoke(chain, args, invocable);
                    Type type = null;
                    if (asyncMethod.getReturnType() == Future.class) {
                        // For callback async menthod
                        Type[] types = asyncMethod.getGenericParameterTypes();
                        if (types.length > 0 && asyncMethod.getParameterTypes()[types.length - 1] == AsyncHandler.class) {
                            // Last paremeter, AsyncHandler<T>
                            type = types[types.length - 1];
                        }
                    } else if (asyncMethod.getReturnType() == Response.class) {
                        // For the polling method, Response<T>
                        type = asyncMethod.getGenericReturnType();
                    }
                    if (type instanceof ParameterizedType) {
                        // Check if the parameterized type of Response<T> is a doc-lit-wrapper class
                        Class<?> wrapperClass = (Class<?>)((ParameterizedType)type).getActualTypeArguments()[0];
                        WrapperInfo wrapperInfo = chain.getSourceOperation().getWrapper();
                        if (wrapperInfo != null && wrapperInfo.getOutputWrapperClass() == wrapperClass) {
                            Object wrapper = wrapperClass.newInstance();
                            // Find the 1st matching property
                            for (PropertyDescriptor p : Introspector.getBeanInfo(wrapperClass).getPropertyDescriptors()) {
                                if (p.getWriteMethod() == null) {
                                    // There is a "class" property ...
                                    continue;
                                }
                                if (p.getWriteMethod().getParameterTypes()[0].isInstance(result)) {
                                    p.getWriteMethod().invoke(wrapper, result);
                                    result = wrapper;
                                    break;
                                }
                            }

                        }
                    }
                    future.setResponse(result);
                } // end if
            } catch (ServiceRuntimeException s) {
                Throwable e = s.getCause();
                if (e != null && e instanceof FaultException) {
                    if ("AsyncResponse".equals(e.getMessage())) {
                        // Do nothing...
                    } else {
                        future.setFault(new AsyncFaultWrapper(s));
                    } // end if
                } // end if
            } catch (AsyncResponseException ar) {
                // do nothing     
            } catch (Throwable t) {
                System.out.println("Async invoke got exception: " + t.toString());
                future.setFault(new AsyncFaultWrapper(t));
            } // end try

        } // end method run

    } // end class separateThreadInvoker

    /**
     * Attaches a future to the callback endpoint - so that the Future is triggered when a response is
     * received from the asynchronous service invocation associated with the Future
     * @param endpoint - the async callback endpoint
     * @param future - the async invocation future to attach
     */
    private void attachFuture(RuntimeEndpoint endpoint, AsyncInvocationFutureImpl<?> future) {
        Implementation impl = endpoint.getComponent().getImplementation();
        AsyncResponseHandlerImpl<?> asyncHandler = (AsyncResponseHandlerImpl<?>)impl;
        asyncHandler.addFuture(future);
    } // end method attachFuture

    /**
     * Get the async callback endpoint - if not already created, create and start it
     * @param source - the RuntimeEndpointReference which needs an async callback endpoint
     * @param future
     * @return - the RuntimeEndpoint of the async callback
     */
    private RuntimeEndpoint getAsyncCallback(Invocable source) {
        if (!(source instanceof RuntimeEndpointReference))
            return null;
        RuntimeEndpointReference epr = (RuntimeEndpointReference)source;
        if (!isAsyncInvocation(epr))
            return null;
        RuntimeEndpoint endpoint;
        synchronized (epr) {
            endpoint = (RuntimeEndpoint)epr.getCallbackEndpoint();
            // If the async callback endpoint is already created, return it...
            if (endpoint != null)
                return endpoint;
            // Create the endpoint for the async callback
            endpoint = createAsyncCallbackEndpoint(epr);
            epr.setCallbackEndpoint(endpoint);
        } // end synchronized

        // Activate the new callback endpoint
        startEndpoint(epr.getCompositeContext(), endpoint);
        endpoint.getInvocationChains();

        return endpoint;
    } // end method setupAsyncCallback

    /**
     * Start the callback endpoint
     * @param compositeContext - the composite context
     * @param ep - the endpoint to start
     */
    private void startEndpoint(CompositeContext compositeContext, RuntimeEndpoint ep) {
        for (PolicyProvider policyProvider : ep.getPolicyProviders()) {
            policyProvider.start();
        } // end for

        final ServiceBindingProvider bindingProvider = ep.getBindingProvider();
        if (bindingProvider != null) {
            // Allow bindings to add shutdown hooks. Requires RuntimePermission shutdownHooks in policy.
            AccessController.doPrivileged(new PrivilegedAction<Object>() {
                public Object run() {
                    bindingProvider.start();
                    return null;
                }
            });
            compositeContext.getEndpointRegistry().addEndpoint(ep);
        }
    } // end method startEndpoint

    /**
     * Create the async callback endpoint for a reference that is going to invoke an asyncInvocation service
     * @param epr - the RuntimeEndpointReference for which the callback is created
     * @return - a RuntimeEndpoint representing the callback endpoint
     */
    private RuntimeEndpoint createAsyncCallbackEndpoint(RuntimeEndpointReference epr) {
        CompositeContext compositeContext = epr.getCompositeContext();
        RuntimeAssemblyFactory assemblyFactory = getAssemblyFactory(compositeContext);
        RuntimeEndpoint endpoint = (RuntimeEndpoint)assemblyFactory.createEndpoint();
        endpoint.bind(compositeContext);

        // Create a pseudo-component and pseudo-service
        // - need to end with a chain with an invoker into the AsyncCallbackHandler class
        RuntimeComponent fakeComponent = null;
        try {
            fakeComponent = (RuntimeComponent)epr.getComponent().clone();
            applyImplementation(fakeComponent);
        } catch (CloneNotSupportedException e2) {
            // will not happen
        } // end try
        endpoint.setComponent(fakeComponent);

        // Create pseudo-service
        ComponentService service = assemblyFactory.createComponentService();
        ExtensionPointRegistry registry = compositeContext.getExtensionPointRegistry();
        FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class);
        JavaInterfaceFactory javaInterfaceFactory =
            (JavaInterfaceFactory)modelFactories.getFactory(JavaInterfaceFactory.class);
        JavaInterfaceContract interfaceContract = javaInterfaceFactory.createJavaInterfaceContract();
        try {
            interfaceContract.setInterface(javaInterfaceFactory.createJavaInterface(AsyncResponseHandler.class));
        } catch (InvalidInterfaceException e1) {
            // Nothing to do here - will not happen
        } // end try
        service.setInterfaceContract(interfaceContract);
        String serviceName = epr.getReference().getName() + "_asyncCallback";
        service.setName(serviceName);
        endpoint.setService(service);
        // Set pseudo-service onto the pseudo-component
        List<ComponentService> services = fakeComponent.getServices();
        services.clear();
        services.add(service);

        // Create a binding
        Binding binding = createMatchingBinding(epr.getBinding(), fakeComponent, service, registry);
        endpoint.setBinding(binding);

        // Need to establish policies here (binding has some...)
        endpoint.getRequiredIntents().addAll(epr.getRequiredIntents());
        endpoint.getPolicySets().addAll(epr.getPolicySets());
        String epURI = epr.getComponent().getName() + "#service-binding(" + serviceName + "/" + serviceName + ")";
        endpoint.setURI(epURI);
        endpoint.setUnresolved(false);
        return endpoint;
    }

    /**
     * Create a matching binding to a supplied binding
     * - the matching binding has the same binding type, but is for the supplied component and service
     * @param matchBinding - the binding to match
     * @param component - the component
     * @param service - the service
     * @param registry - registry for extensions
     * @return - the matching binding, or null if it could not be created
     */
    @SuppressWarnings("unchecked")
    private Binding createMatchingBinding(Binding matchBinding,
                                          RuntimeComponent component,
                                          ComponentService service,
                                          ExtensionPointRegistry registry) {
        // Since there is no simple way to obtain a Factory for a binding where the type is not known ahead of
        // time, the process followed here is to generate the <binding.xxx/> XML element from the binding type QName
        // and then read the XML using the processor for that XML...
        QName bindingName = matchBinding.getType();
        String bindingXML =
            "<ns1:" + bindingName.getLocalPart() + " xmlns:ns1='" + bindingName.getNamespaceURI() + "'/>";

        StAXArtifactProcessorExtensionPoint processors =
            registry.getExtensionPoint(StAXArtifactProcessorExtensionPoint.class);
        StAXArtifactProcessor<?> processor = (StAXArtifactProcessor<?>)processors.getProcessor(bindingName);

        FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class);
        ValidatingXMLInputFactory inputFactory = modelFactories.getFactory(ValidatingXMLInputFactory.class);
        StreamSource source = new StreamSource(new StringReader(bindingXML));

        ProcessorContext context = new ProcessorContext();
        try {
            XMLStreamReader reader = inputFactory.createXMLStreamReader(source);
            reader.next();
            Binding newBinding = (Binding)processor.read(reader, context);

            // Create a URI address for the callback based on the Component_Name/Reference_Name pattern
            String callbackURI = "/" + component.getName() + "/" + service.getName();
            newBinding.setURI(callbackURI);

            BuilderExtensionPoint builders = registry.getExtensionPoint(BuilderExtensionPoint.class);
            BindingBuilder builder = builders.getBindingBuilder(newBinding.getType());
            if (builder != null) {
                org.apache.tuscany.sca.assembly.builder.BuilderContext builderContext = new BuilderContext(registry);
                builder.build(component, service, newBinding, builderContext, true);
            } // end if

            return newBinding;
        } catch (ContributionReadException e) {
            e.printStackTrace();
        } catch (XMLStreamException e) {
            e.printStackTrace();
        }

        return null;
    } // end method createMatchingBinding

    /**
     * Gets a RuntimeAssemblyFactory from the CompositeContext
     * @param compositeContext
     * @return the RuntimeAssemblyFactory
     */
    private RuntimeAssemblyFactory getAssemblyFactory(CompositeContext compositeContext) {
        ExtensionPointRegistry registry = compositeContext.getExtensionPointRegistry();
        FactoryExtensionPoint modelFactories = registry.getExtensionPoint(FactoryExtensionPoint.class);
        return (RuntimeAssemblyFactory)modelFactories.getFactory(AssemblyFactory.class);
    } // end method RuntimeAssemblyFactory

    /**
     * Applies an AsyncResponseHandlerImpl as the implementation of a RuntimeComponent
     * - the AsyncResponseHandlerImpl acts as both the implementation class and the implementation provider...
     * @param component - the component
     */
    private void applyImplementation(RuntimeComponent component) {
        AsyncResponseHandlerImpl<?> asyncHandler = new AsyncResponseHandlerImpl<Object>();
        component.setImplementation(asyncHandler);
        component.setImplementationProvider(asyncHandler);
        return;
    } // end method getImplementationProvider

    private static QName ASYNC_INVOKE = new QName(Constants.SCA11_NS, "asyncInvocation");

    /**
     * Determines if the service invocation is asynchronous
     * @param source - the EPR involved in the invocation
     * @return - true if the invocation is async
     */
    private boolean isAsyncInvocation(Invocable source) {
        if (!(source instanceof RuntimeEndpointReference))
            return false;
        RuntimeEndpointReference epr = (RuntimeEndpointReference)source;
        // First check is to see if the EPR itself has the asyncInvocation intent marked
        for (Intent intent : epr.getRequiredIntents()) {
            if (intent.getName().equals(ASYNC_INVOKE))
                return true;
        } // end for

        // Second check is to see if the target service has the asyncInvocation intent marked
        Endpoint ep = epr.getTargetEndpoint();
        for (Intent intent : ep.getRequiredIntents()) {
            if (intent.getName().equals(ASYNC_INVOKE))
                return true;
        } // end for
        return false;
    } // end isAsyncInvocation

    /**
     * Return the synchronous method that is the equivalent of an async method
     * @param asyncMethod - the async method
     * @return - the equivalent synchronous method
     */
    protected Method getNonAsyncMethod(Method asyncMethod) {
        String methodName = asyncMethod.getName().substring(0, asyncMethod.getName().length() - 5);
        for (Method m : businessInterface.getMethods()) {
            if (methodName.equals(m.getName())) {
                return m;
            }
        }
        throw new IllegalStateException("No synchronous method matching async method " + asyncMethod.getName());
    } // end method getNonAsyncMethod

    /**
     * Gets the classloader of the business interface
     * @return
     */
    private ClassLoader getInterfaceClassloader() {
        return businessInterface.getClassLoader();
    }
}
TOP

Related Classes of org.apache.tuscany.sca.core.invocation.impl.AsyncJDKInvocationHandler

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.