diff options
Diffstat (limited to 'sca-java-2.x/trunk/modules/interface-java-jaxws/src')
4 files changed, 159 insertions, 95 deletions
diff --git a/sca-java-2.x/trunk/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/JAXWSAsyncInterfaceProcessor.java b/sca-java-2.x/trunk/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/JAXWSAsyncInterfaceProcessor.java index 155c89c7f2..a866c5b8e1 100644 --- a/sca-java-2.x/trunk/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/JAXWSAsyncInterfaceProcessor.java +++ b/sca-java-2.x/trunk/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/JAXWSAsyncInterfaceProcessor.java @@ -20,48 +20,54 @@ package org.apache.tuscany.sca.interfacedef.java.jaxws; import java.lang.reflect.ParameterizedType; +import java.lang.reflect.Type; import java.util.ArrayList; import java.util.List; +import java.util.concurrent.Future; + +import javax.xml.ws.AsyncHandler; +import javax.xml.ws.Response; import org.apache.tuscany.sca.core.ExtensionPointRegistry; import org.apache.tuscany.sca.interfacedef.DataType; import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; import org.apache.tuscany.sca.interfacedef.Operation; import org.apache.tuscany.sca.interfacedef.java.JavaInterface; +import org.apache.tuscany.sca.interfacedef.java.JavaOperation; import org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceVisitor; public class JAXWSAsyncInterfaceProcessor implements JavaInterfaceVisitor { private static String ASYNC = "Async"; public JAXWSAsyncInterfaceProcessor(ExtensionPointRegistry registry) { - } - + public void visitInterface(JavaInterface javaInterface) throws InvalidInterfaceException { List<Operation> validOperations = new ArrayList<Operation>(); List<Operation> asyncOperations = new ArrayList<Operation>(); - + validOperations.addAll(javaInterface.getOperations()); - for(Operation o : javaInterface.getOperations()) { - if (! o.getName().endsWith(ASYNC)) { - Operation op = o; - - for(Operation asyncOp : getAsyncOperations(javaInterface.getOperations(), o.getName()) ) { - if (isJAXWSAsyncPoolingOperation(op, asyncOp) || - isJAXWSAsyncCallbackOperation(op, asyncOp)) { + for (Operation o : javaInterface.getOperations()) { + if (!o.getName().endsWith(ASYNC)) { + JavaOperation op = (JavaOperation)o; + if (op.getJavaMethod().getName().endsWith(ASYNC)) { + continue; + } + for (Operation asyncOp : getAsyncOperations(javaInterface.getOperations(), op)) { + if (isJAXWSAsyncPoolingOperation(op, asyncOp) || isJAXWSAsyncCallbackOperation(op, asyncOp)) { validOperations.remove(asyncOp); asyncOperations.add(asyncOp); - } + } } - } + } } - + javaInterface.getOperations().clear(); javaInterface.getOperations().addAll(validOperations); - + javaInterface.getAttributes().put("JAXWS-ASYNC-OPERATIONS", asyncOperations); } - + /** * The additional client-side asynchronous polling and callback methods defined by JAX-WS are recognized in a Java interface as follows: * For each method M in the interface, if another method P in the interface has @@ -75,53 +81,59 @@ public class JAXWSAsyncInterfaceProcessor implements JavaInterfaceVisitor { * @return */ private static boolean isJAXWSAsyncPoolingOperation(Operation operation, Operation asyncOperation) { - //a method name that is M's method name with the characters "Async" appended - if (operation.getName().endsWith(ASYNC)) { - return false; - } - if (! asyncOperation.getName().endsWith(ASYNC)) { + if (asyncOperation.getOutputType() == null || Response.class != asyncOperation.getOutputType().getPhysical()) { + // The return type is not Response<T> return false; } - - if(! asyncOperation.getName().equals(operation.getName() + ASYNC)) { - return false; - } - + //the same parameter signature as M List<DataType> operationInputType = operation.getInputType().getLogical(); List<DataType> asyncOperationInputType = asyncOperation.getInputType().getLogical(); int size = operationInputType.size(); + if (asyncOperationInputType.size() != size) { + return false; + } for (int i = 0; i < size; i++) { if (!isCompatible(operationInputType.get(i), asyncOperationInputType.get(i))) { return false; } } - + //a return type of Response<R> where R is the return type of M DataType<?> operationOutputType = operation.getOutputType(); DataType<?> asyncOperationOutputType = asyncOperation.getOutputType(); - + if (operationOutputType != null && asyncOperationOutputType != null) { - ParameterizedType asyncReturnType = (ParameterizedType) asyncOperationOutputType.getGenericType(); - Class<?> asyncReturnTypeClass = (Class<?>)asyncReturnType.getRawType(); - if(asyncReturnTypeClass.getName().equals("javax.xml.ws.Response")) { + Class<?> asyncReturnTypeClass = (Class<?>)asyncOperationOutputType.getPhysical(); + if (asyncReturnTypeClass == Response.class) { //now check the actual type of the Response<R> with R - Class<?> returnType = operationOutputType.getPhysical(); - Class<?> asyncActualReturnTypeClass = (Class<?>) asyncReturnType.getActualTypeArguments()[0]; - - if(returnType == asyncActualReturnTypeClass || - returnType.isPrimitive() && primitiveAssignable(returnType,asyncActualReturnTypeClass)) { - //valid - } else { - return false; + Class<?> returnType = operationOutputType.getPhysical(); + Class<?> asyncActualReturnTypeClass = Object.class; + if (asyncOperationOutputType.getGenericType() instanceof ParameterizedType) { + ParameterizedType asyncReturnType = (ParameterizedType)asyncOperationOutputType.getGenericType(); + asyncActualReturnTypeClass = (Class<?>)asyncReturnType.getActualTypeArguments()[0]; + } + + if (operation.getWrapper() != null) { + // The return type could be the wrapper type per JAX-WS spec + Class<?> wrapperClass = operation.getWrapper().getOutputWrapperClass(); + if (wrapperClass == asyncActualReturnTypeClass) { + return true; + } + } + if (returnType == asyncActualReturnTypeClass || returnType.isPrimitive() + && primitiveAssignable(returnType, asyncActualReturnTypeClass)) { + return true; + } else { + return false; } } } - + return true; } - + /** * For each method M in the interface, if another method C in the interface has * a) a method name that is M's method name with the characters "Async" appended, and @@ -136,71 +148,57 @@ public class JAXWSAsyncInterfaceProcessor implements JavaInterfaceVisitor { * @return */ private static boolean isJAXWSAsyncCallbackOperation(Operation operation, Operation asyncOperation) { - //a method name that is M's method name with the characters "Async" appended - if (operation.getName().endsWith(ASYNC)) { - return false; - } - if (! asyncOperation.getName().endsWith(ASYNC)) { - return false; - } - - if(! asyncOperation.getName().equals(operation.getName() + ASYNC)) { + if (asyncOperation.getOutputType() == null || Future.class != asyncOperation.getOutputType().getPhysical()) { + // The return type is not Future<?> return false; } - + //a parameter signature that is M's parameter signature //with an additional final parameter of type AsyncHandler<R> where R is the return type of M, and List<DataType> operationInputType = operation.getInputType().getLogical(); List<DataType> asyncOperationInputType = asyncOperation.getInputType().getLogical(); int size = operationInputType.size(); + if (asyncOperationInputType.size() != size + 1) { + return false; + } for (int i = 0; i < size; i++) { if (!isCompatible(operationInputType.get(i), asyncOperationInputType.get(i))) { return false; } } - - if(asyncOperationInputType.size() == size + 1) { - ParameterizedType asyncLastParameterType = (ParameterizedType) asyncOperationInputType.get(size + 1).getGenericType(); - Class<?> asyncLastParameterTypeClass = (Class<?>)asyncLastParameterType.getRawType(); - if(asyncLastParameterTypeClass.getName().equals("javax.xml.ws.AsyncHandler")) { - //now check the actual type of the AsyncHandler<R> with R - Class<?> returnType = operation.getOutputType().getPhysical(); - Class<?> asyncActualLastParameterTypeClass = (Class<?>) asyncLastParameterType.getActualTypeArguments()[0]; - - if(returnType == asyncActualLastParameterTypeClass || - returnType.isPrimitive() && primitiveAssignable(returnType,asyncActualLastParameterTypeClass)) { - //valid - } else { - return false; - } - } - } - - //a return type of Response<R> where R is the return type of M - DataType<?> operationOutputType = operation.getOutputType(); - DataType<?> asyncOperationOutputType = asyncOperation.getOutputType(); - - if (operationOutputType != null && asyncOperationOutputType != null) { - ParameterizedType asyncReturnType = (ParameterizedType) asyncOperationOutputType.getGenericType(); - Class<?> asyncReturnTypeClass = (Class<?>)asyncReturnType.getRawType(); - if(asyncReturnTypeClass.getName().equals("javax.xml.ws.Response")) { - //now check the actual type of the Response<R> with R - Class<?> returnType = operationOutputType.getPhysical(); - Class<?> asyncActualReturnTypeClass = (Class<?>) asyncReturnType.getActualTypeArguments()[0]; - - if(returnType == asyncActualReturnTypeClass || - returnType.isPrimitive() && primitiveAssignable(returnType,asyncActualReturnTypeClass)) { - //valid - } else { - return false; + + Type genericParamType = asyncOperationInputType.get(size).getGenericType(); + + Class<?> asyncLastParameterTypeClass = asyncOperationInputType.get(size).getPhysical(); + if (asyncLastParameterTypeClass == AsyncHandler.class) { + //now check the actual type of the AsyncHandler<R> with R + Class<?> returnType = operation.getOutputType().getPhysical(); + Class<?> asyncActualLastParameterTypeClass = Object.class; + if (genericParamType instanceof ParameterizedType) { + ParameterizedType asyncLastParameterType = (ParameterizedType)genericParamType; + asyncActualLastParameterTypeClass = (Class<?>)asyncLastParameterType.getActualTypeArguments()[0]; + } + + if (operation.getWrapper() != null) { + // The return type could be the wrapper type per JAX-WS spec + Class<?> wrapperClass = operation.getWrapper().getOutputWrapperClass(); + if (wrapperClass == asyncActualLastParameterTypeClass) { + return true; } } + + if (returnType == asyncActualLastParameterTypeClass || returnType.isPrimitive() + && primitiveAssignable(returnType, asyncActualLastParameterTypeClass)) { + return true; + } else { + return false; + } } - + return true; - } - + } + /** * Get operation by name * @@ -208,18 +206,30 @@ public class JAXWSAsyncInterfaceProcessor implements JavaInterfaceVisitor { * @param operationName * @return */ - private static List<Operation> getAsyncOperations(List<Operation> operations, String operationName) { + private static List<Operation> getAsyncOperations(List<Operation> operations, JavaOperation op) { List<Operation> returnOperations = new ArrayList<Operation>(); - for(Operation o : operations) { - if(o.getName().equals(operationName + ASYNC)) { + for (Operation o : operations) { + if (o == op) { + continue; + } + String operationName = op.getName(); + if (o.getName().equals(operationName)) { + // Async operations have the same name when @WebMethod is present + /* + JavaOperation jop = (JavaOperation)o; + if (op.getJavaMethod().getName().equals(jop.getJavaMethod().getName() + ASYNC)) { + returnOperations.add(o); + } + */ + returnOperations.add(o); + } else if (o.getName().equals(operationName + ASYNC)) { returnOperations.add(o); } } - + return returnOperations; } - /** * Check if two operation parameters are compatible diff --git a/sca-java-2.x/trunk/modules/interface-java-jaxws/src/main/resources/META-INF/services/org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceVisitor b/sca-java-2.x/trunk/modules/interface-java-jaxws/src/main/resources/META-INF/services/org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceVisitor index 86255f4fef..05b1ccea9b 100644 --- a/sca-java-2.x/trunk/modules/interface-java-jaxws/src/main/resources/META-INF/services/org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceVisitor +++ b/sca-java-2.x/trunk/modules/interface-java-jaxws/src/main/resources/META-INF/services/org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceVisitor @@ -13,7 +13,11 @@ # "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. +# under the License. +# +# first one, set remotable flag org.apache.tuscany.sca.interfacedef.java.jaxws.WebServiceInterfaceProcessor;ranking=400 +# second one, introspect the JAXWS annotations org.apache.tuscany.sca.interfacedef.java.jaxws.JAXWSJavaInterfaceProcessor;ranking=100 -org.apache.tuscany.sca.interfacedef.java.jaxws.JAXWSAsyncInterfaceProcessor;ranking=900
+# third one, introspect JAXWS async methods +org.apache.tuscany.sca.interfacedef.java.jaxws.JAXWSAsyncInterfaceProcessor;ranking=50
diff --git a/sca-java-2.x/trunk/modules/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/JAXWSAsyncInterfaceProcessorTestCase.java b/sca-java-2.x/trunk/modules/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/JAXWSAsyncInterfaceProcessorTestCase.java index ec73ad4218..c53521db00 100644 --- a/sca-java-2.x/trunk/modules/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/JAXWSAsyncInterfaceProcessorTestCase.java +++ b/sca-java-2.x/trunk/modules/interface-java-jaxws/src/test/java/org/apache/tuscany/sca/interfacedef/java/jaxws/JAXWSAsyncInterfaceProcessorTestCase.java @@ -33,6 +33,8 @@ import org.apache.tuscany.sca.interfacedef.java.JavaInterface; import org.junit.Before; import org.junit.Test; +import com.example.stock.async.StockExceptionTest; + public class JAXWSAsyncInterfaceProcessorTestCase { private ExtensionPointRegistry registry; @@ -64,4 +66,24 @@ public class JAXWSAsyncInterfaceProcessorTestCase { } } + + @Test + public final void testProcessorGenerated() throws Exception { + DefaultJavaInterfaceFactory iFactory = new DefaultJavaInterfaceFactory(registry); + JavaInterface contract = iFactory.createJavaInterface(StockExceptionTest.class); + + assertTrue(contract.isRemotable()); + + Assert.assertEquals(1,contract.getOperations().size()); + + List<Operation> asyncOperations = (List<Operation>) contract.getAttributes().get("JAXWS-ASYNC-OPERATIONS"); + Assert.assertEquals(2,asyncOperations.size()); + + //list operation + System.out.println(">>> Filtered Operations"); + for(Operation o : contract.getOperations()) { + System.out.println(">>>>>>" + o); + } + + } } diff --git a/sca-java-2.x/trunk/modules/interface-java-jaxws/src/test/resources/wsdl/bindings.xml b/sca-java-2.x/trunk/modules/interface-java-jaxws/src/test/resources/wsdl/bindings.xml new file mode 100644 index 0000000000..078abb5ac1 --- /dev/null +++ b/sca-java-2.x/trunk/modules/interface-java-jaxws/src/test/resources/wsdl/bindings.xml @@ -0,0 +1,28 @@ +<?xml version="1.0" encoding="UTF-8"?> +<!-- + * 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. +--> +<bindings + xmlns:xsd="http://www.w3.org/2001/XMLSchema" + xmlns:wsdl="http://schemas.xmlsoap.org/wsdl/" + wsdlLocation="StockExceptionTest.wsdl" + xmlns="http://java.sun.com/xml/ns/jaxws"> + <bindings node="wsdl:definitions"> + <enableAsyncMapping>true</enableAsyncMapping> + </bindings> +</bindings> |