| /* |
| * 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(); |
| } |
| } |