diff options
author | antelder <antelder@13f79535-47bb-0310-9956-ffa450edef68> | 2009-10-23 10:18:42 +0000 |
---|---|---|
committer | antelder <antelder@13f79535-47bb-0310-9956-ffa450edef68> | 2009-10-23 10:18:42 +0000 |
commit | 4e8a796b4dfba27549f5d91a3e269c84e99a9d14 (patch) | |
tree | 241ff9fc830e93a450b895b2c3c8004707f95065 /java | |
parent | b1f09c1c389f634fe5cf7836898aa9d01aa82e42 (diff) |
Add example of runtime support for handling JAXWS async client APIs
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@828988 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to '')
3 files changed, 190 insertions, 1 deletions
diff --git a/java/sca/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncJDKInvocationHandler.java b/java/sca/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncJDKInvocationHandler.java new file mode 100644 index 0000000000..aeccfa8b05 --- /dev/null +++ b/java/sca/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncJDKInvocationHandler.java @@ -0,0 +1,93 @@ +/*
+ * 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.lang.reflect.Method;
+import java.util.Arrays;
+import java.util.concurrent.Future;
+
+import javax.xml.ws.AsyncHandler;
+import javax.xml.ws.Response;
+
+import org.apache.tuscany.sca.invocation.MessageFactory;
+import org.oasisopen.sca.ServiceReference;
+
+public class AsyncJDKInvocationHandler extends JDKInvocationHandler {
+ private static final long serialVersionUID = 1L;
+
+ public AsyncJDKInvocationHandler(MessageFactory messageFactory, ServiceReference<?> callableReference) {
+ super(messageFactory, callableReference);
+ }
+
+ @Override
+ public Object invoke(Object proxy, Method method, Object[] args) throws Throwable {
+ if (isAsyncCallback(method)) {
+ return doInvokeAsyncCallback(proxy, method, args);
+ } else if (isAsyncPoll(method)) {
+ return doInvokeAsyncPoll(proxy, method, args);
+ } else {
+ return super.invoke(proxy, method, args);
+ }
+ }
+
+ protected boolean isAsyncCallback(Method method) {
+ if (method.getName().endsWith("Async") && (method.getReturnType().isAssignableFrom(Future.class))) {
+ if (method.getParameterTypes().length > 0) {
+ return method.getParameterTypes()[method.getParameterTypes().length-1].isAssignableFrom(AsyncHandler.class);
+ }
+ }
+ return false;
+ }
+
+ protected boolean isAsyncPoll(Method method) {
+ return method.getName().endsWith("Async") && (method.getReturnType().isAssignableFrom(Response.class));
+ }
+
+ protected AsyncResponse doInvokeAsyncPoll(Object proxy, Method asyncMethod, Object[] args) {
+ Object response;
+ boolean isException;
+ try {
+ response = super.invoke(proxy, getNonAsyncMethod(asyncMethod), args);
+ isException = false;
+ } catch (Throwable e) {
+ response = e;
+ isException = true;
+ }
+ return new AsyncResponse(response, isException);
+ }
+
+ private Object doInvokeAsyncCallback(Object proxy, Method asyncMethod, Object[] args) {
+ AsyncHandler handler = (AsyncHandler)args[args.length-1];
+ Response response = doInvokeAsyncPoll(proxy,asyncMethod,Arrays.copyOf(args, args.length-1));
+ handler.handleResponse(response);
+
+ return null;
+ }
+
+ 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 non-async method matching async method " + asyncMethod.getName());
+ }
+}
diff --git a/java/sca/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncResponse.java b/java/sca/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncResponse.java new file mode 100644 index 0000000000..07086dfae3 --- /dev/null +++ b/java/sca/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/AsyncResponse.java @@ -0,0 +1,68 @@ +/*
+ * 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.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.ExecutionException;
+import java.util.concurrent.TimeUnit;
+import java.util.concurrent.TimeoutException;
+
+import javax.xml.ws.Response;
+
+public class AsyncResponse implements Response {
+
+ private Object response;
+ private boolean isException;
+
+ public AsyncResponse(Object response, boolean isException) {
+ this.response = response;
+ this.isException = isException;
+ }
+
+ public Map getContext() {
+ return new HashMap();
+ }
+
+ public boolean cancel(boolean mayInterruptIfRunning) {
+ return false;
+ }
+
+ public Object get() throws InterruptedException, ExecutionException {
+ if (isException) {
+ throw new ExecutionException((Throwable)response);
+ } else {
+ return response;
+ }
+ }
+
+ public Object get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException {
+ return get();
+ }
+
+ public boolean isCancelled() {
+ return false;
+ }
+
+ public boolean isDone() {
+ return true;
+ }
+
+}
diff --git a/java/sca/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKProxyFactory.java b/java/sca/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKProxyFactory.java index e0d0a40985..853e28fafa 100644 --- a/java/sca/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKProxyFactory.java +++ b/java/sca/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKProxyFactory.java @@ -20,10 +20,15 @@ package org.apache.tuscany.sca.core.invocation.impl; import java.lang.reflect.Constructor; import java.lang.reflect.InvocationHandler; +import java.lang.reflect.Method; import java.lang.reflect.Proxy; import java.security.AccessController; import java.security.PrivilegedAction; import java.util.List; +import java.util.concurrent.Future; + +import javax.xml.ws.AsyncHandler; +import javax.xml.ws.Response; import org.apache.tuscany.sca.common.java.collection.LRUCache; import org.apache.tuscany.sca.core.LifeCycleListener; @@ -63,7 +68,12 @@ public class JDKProxyFactory implements ProxyFactory, LifeCycleListener { public <T> T createProxy(ServiceReference<T> callableReference) throws ProxyCreationException { assert callableReference != null; final Class<T> interfaze = callableReference.getBusinessInterface(); - InvocationHandler handler = new JDKInvocationHandler(messageFactory, callableReference); + InvocationHandler handler; + if (isAsync(interfaze)) { + handler = new AsyncJDKInvocationHandler(messageFactory, callableReference); + } else { + handler = new JDKInvocationHandler(messageFactory, callableReference); + } // Allow privileged access to class loader. Requires RuntimePermission in security policy. ClassLoader cl = AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() { public ClassLoader run() { @@ -74,6 +84,24 @@ public class JDKProxyFactory implements ProxyFactory, LifeCycleListener { ((ServiceReferenceImpl)callableReference).setProxy(proxy); return interfaze.cast(proxy); } + + private boolean isAsync(Class<?> interfaze) { + for (Method method : interfaze.getMethods()) { + if (method.getName().endsWith("Async")) { + if (method.getReturnType().isAssignableFrom(Future.class)) { + if (method.getParameterTypes().length > 0) { + if (method.getParameterTypes()[method.getParameterTypes().length-1].isAssignableFrom(AsyncHandler.class)) { + return true; + } + } + } + if (method.getReturnType().isAssignableFrom(Response.class)) { + return true; + } + } + } + return false; + } public <T> T createCallbackProxy(Class<T> interfaze, List<RuntimeWire> wires) throws ProxyCreationException { ServiceReferenceImpl<T> callbackReference = new CallbackServiceReferenceImpl(interfaze, wires, this); |