Author: edwardsmj
Date: Fri Jun 25 10:21:28 2010
New Revision: 957877
URL: http://svn.apache.org/viewvc?rev=957877&view=rev
Log:
Introspection of SCA Async Server form on Java interface and Equivalence
mapping of Async Server interface to Synchronous Java interface, as described
in TUSCANY-3609 and TUSCANY-3610
Modified:
tuscany/sca-java-2.x/trunk/modules/interface-java/META-INF/MANIFEST.MF
tuscany/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaOperation.java
tuscany/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceFactoryImpl.java
tuscany/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceImpl.java
tuscany/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceIntrospectorImpl.java
tuscany/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceUtil.java
tuscany/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaOperationImpl.java
Modified: tuscany/sca-java-2.x/trunk/modules/interface-java/META-INF/MANIFEST.MF
URL:
http://svn.apache.org/viewvc/tuscany/sca-java-2.x/trunk/modules/interface-java/META-INF/MANIFEST.MF?rev=957877&r1=957876&r2=957877&view=diff
==============================================================================
--- tuscany/sca-java-2.x/trunk/modules/interface-java/META-INF/MANIFEST.MF
(original)
+++ tuscany/sca-java-2.x/trunk/modules/interface-java/META-INF/MANIFEST.MF Fri
Jun 25 10:21:28 2010
@@ -21,6 +21,7 @@ Bundle-License: http://www.apache.org/li
Bundle-Description: Apache Tuscany SCA Java Interface Model
Import-Package: javax.xml.namespace,
javax.xml.stream,
+ org.oasisopen.sca;version="2.0.0",
org.apache.tuscany.sca.assembly;version="2.0.0",
org.apache.tuscany.sca.assembly.xml;version="2.0.0",
org.apache.tuscany.sca.contribution.processor;version="2.0.0",
Modified:
tuscany/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaOperation.java
URL:
http://svn.apache.org/viewvc/tuscany/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaOperation.java?rev=957877&r1=957876&r2=957877&view=diff
==============================================================================
---
tuscany/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaOperation.java
(original)
+++
tuscany/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/JavaOperation.java
Fri Jun 25 10:21:28 2010
@@ -54,5 +54,17 @@ public interface JavaOperation extends O
* @param action the action value
*/
void setAction(String action);
+
+ /**
+ * Sets whether this operation has async server style
+ * @param isAsync - "true" marks this operation as async server style
+ */
+ public void setAsyncServer( boolean isAsync );
+
+ /**
+ * Indicates whether this operation is async server style
+ * @return - true if the operation is async server style
+ */
+ public boolean isAsyncServer();
}
Modified:
tuscany/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceFactoryImpl.java
URL:
http://svn.apache.org/viewvc/tuscany/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceFactoryImpl.java?rev=957877&r1=957876&r2=957877&view=diff
==============================================================================
---
tuscany/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceFactoryImpl.java
(original)
+++
tuscany/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceFactoryImpl.java
Fri Jun 25 10:21:28 2010
@@ -58,6 +58,8 @@ public abstract class JavaInterfaceFacto
if (javaInterface == null) {
javaInterface = createJavaInterface();
introspector.introspectInterface(javaInterface,
interfaceClass);
+ // Now that all introspection is complete we can mark the
interface resolved
+ javaInterface.setUnresolved(false);
cache.put(interfaceClass, javaInterface);
}
return javaInterface;
Modified:
tuscany/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceImpl.java
URL:
http://svn.apache.org/viewvc/tuscany/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceImpl.java?rev=957877&r1=957876&r2=957877&view=diff
==============================================================================
---
tuscany/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceImpl.java
(original)
+++
tuscany/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceImpl.java
Fri Jun 25 10:21:28 2010
@@ -19,10 +19,25 @@
package org.apache.tuscany.sca.interfacedef.java.impl;
import java.lang.ref.WeakReference;
+import java.lang.reflect.Type;
+import java.lang.reflect.TypeVariable;
+import java.util.ArrayList;
+import java.util.List;
+import java.lang.reflect.ParameterizedType;
import javax.xml.namespace.QName;
+
+import org.apache.tuscany.sca.assembly.xml.Constants;
+import org.apache.tuscany.sca.interfacedef.DataType;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl;
import org.apache.tuscany.sca.interfacedef.impl.InterfaceImpl;
import org.apache.tuscany.sca.interfacedef.java.JavaInterface;
+import org.apache.tuscany.sca.interfacedef.java.JavaOperation;
+import org.apache.tuscany.sca.interfacedef.util.XMLType;
+import org.apache.tuscany.sca.policy.Intent;
+
+import org.oasisopen.sca.ResponseDispatch;
/**
* Represents a Java interface.
@@ -37,6 +52,10 @@ public class JavaInterfaceImpl extends I
private QName qname;
protected JavaInterfaceImpl() {
+ super();
+ // Mark the interface as unresolved until all the basic processing is
complete
+ // including Intent & Policy introspection
+ this.setUnresolved(true);
}
public String getName() {
@@ -135,5 +154,172 @@ public class JavaInterfaceImpl extends I
return true;
}
+
+ public List<Operation> getOperations() {
+ if( !isUnresolved() && isAsyncServer() ) {
+ return equivalentSyncOperations();
+ } else {
+ return super.getOperations();
+ }
+ } // end method getOperations
+
+
+ private List<Operation> syncOperations = null;
+ private List<Operation> equivalentSyncOperations() {
+ if( syncOperations != null ) return syncOperations;
+ List<Operation> allOperations = super.getOperations();
+ syncOperations = new ArrayList<Operation>();
+ for( Operation operation: allOperations) {
+ syncOperations.add( getSyncFormOfOperation( (JavaOperation)
operation ) );
+ // Store the actual async operations under the attribute
"ASYNC-SERVER-OPERATIONS"
+ this.getAttributes().put("ASYNC-SERVER-OPERATIONS", allOperations);
+ } // end for
+
+ return syncOperations;
+ } // end method equivalentSyncOperations
+
+ private static final String UNKNOWN_DATABINDING = null;
+ /**
+ * Prepares the synchronous form of an asynchronous operation
+ * - async form: void someOperationAsync( FooType inputParam,
DispatchResponse<BarType> )
+ * - sync form: BarType someOperation( FooType inputParam )
+ * @param operation - the operation to convert
+ * @return - the synchronous form of the operation - for an input
operation that is not async server in form, this
+ * method simply returns the original operation unchanged
+ */
+ private Operation getSyncFormOfOperation( JavaOperation operation ) {
+ if( isAsyncServerOperation( operation ) ) {
+ JavaOperation syncOperation = new JavaOperationImpl();
+ String opName = operation.getName().substring(0,
operation.getName().length() - 5 );
+
+ // Prepare the list of equivalent input parameters, which simply
excludes the (final) DispatchResponse object
+ // and the equivalent return parameter, which is the (generic)
type from the DispatchResponse object
+ DataType<List<DataType>> requestParams = operation.getInputType();
+
+ DataType<List<DataType>> inputType = prepareSyncInputParams(
requestParams );
+ DataType<XMLType> returnDataType = prepareSyncReturnParam(
requestParams );
+ List<DataType> faultDataTypes = prepareSyncFaults( operation );
+
+ syncOperation.setName(opName);
+ syncOperation.setAsyncServer(true);
+ syncOperation.setInputType(inputType);
+ syncOperation.setOutputType(returnDataType);
+ syncOperation.setFaultTypes(faultDataTypes);
+ syncOperation.setNonBlocking(operation.isNonBlocking());
+ syncOperation.setJavaMethod(operation.getJavaMethod());
+ syncOperation.setInterface(this);
+ return syncOperation;
+ } else {
+ // If it's not Async form, then it's a synchronous operation
+ return operation;
+ } // end if
+ } // end getSyncFormOfOperation
+
+ /**
+ * Produce the equivalent sync method input parameters from the input
parameters of the async method
+ * @param requestParams - async method input parameters
+ * @return - the equivalent sync method input parameters
+ */
+ private DataType<List<DataType>> prepareSyncInputParams(
DataType<List<DataType>> requestParams ) {
+ List<DataType> requestLogical = requestParams.getLogical();
+ int paramCount = requestLogical.size();
+
+ // Copy the list of async parameters, removing the final
DispatchResponse
+ List<DataType> asyncParams = new ArrayList<DataType>( paramCount - 1);
+ for( int i = 0 ; i < (paramCount - 1) ; i++ ) {
+ asyncParams.add( requestLogical.get(i) );
+ } // end for
+
+ DataType<List<DataType>> inputType =
+ new DataTypeImpl<List<DataType>>(requestParams.getDataBinding(),
+ requestParams.getPhysical(),
asyncParams);
+ return inputType;
+ } // end method prepareSyncInputParams
+
+ /**
+ * Prepare the return data type of the equivalent sync operation, based on
the parameterization of the ResponseDispatch object
+ * of the async operation - the return data type is the Generic type of
the final DispatchResponse<?>
+ * @param requestParams - - async method input parameters
+ * @return - the sync method return parameter
+ */
+ private DataType<XMLType> prepareSyncReturnParam( DataType<List<DataType>>
requestParams ) {
+ List<DataType> requestLogical = requestParams.getLogical();
+ int paramCount = requestLogical.size();
+
+ DataType<?> finalParam = requestLogical.get( paramCount - 1 );
+ ParameterizedType t = (ParameterizedType)finalParam.getGenericType();
+ XMLType returnXMLType = (XMLType)finalParam.getLogical();
+
+ String namespace = null;
+ if( returnXMLType.isElement() ) {
+ namespace = returnXMLType.getElementName().getNamespaceURI();
+ } else {
+ namespace = returnXMLType.getTypeName().getNamespaceURI();
+ }
+
+ Type[] typeArgs = t.getActualTypeArguments();
+ if( typeArgs.length != 1 ) throw new IllegalArgumentException(
"ResponseDispatch parameter is not parameterized correctly");
+
+ Class<?> returnType = (Class<?>)typeArgs[0];
+
+ // Set outputType to null for void
+ XMLType xmlReturnType = new XMLType(new QName(namespace, "return"),
null);
+ DataType<XMLType> returnDataType =
+ returnType == void.class ? null : new
DataTypeImpl<XMLType>(UNKNOWN_DATABINDING, returnType, xmlReturnType);
+
+ return returnDataType;
+ } // end method prepareSyncReturnParam
+
+ /**
+ * Prepare the set of equivalent sync faults for a given async operation
+ * @return - the list of faults
+ */
+ private List<DataType> prepareSyncFaults( JavaOperation operation ) {
+ //TODO - deal with Faults - for now just copy through whatever is
associated with the async operation
+ return operation.getFaultTypes();
+ }
+
+ /**
+ * Determines if an interface operation has the form of an async server
operation
+ * - async form: void someOperationAsync( FooType inputParam, ....,
DispatchResponse<BarType> )
+ * @param operation - the operation to examine
+ * @return - true if the operation has the form of an async operation,
false otherwise
+ */
+ private boolean isAsyncServerOperation( Operation operation ) {
+ // Async form operations have:
+ // 1) void return type
+ // 2) name ending in "Async"
+ // 3) final parameter which is of ResponseDispatch<?> type
+ DataType<?> response = operation.getOutputType();
+ if( response != null ) {
+ if ( response.getPhysical() != void.class ) return false;
+ } // end if
+
+ if ( !operation.getName().endsWith("Async") ) return false;
+
+ DataType<List<DataType>> requestParams = operation.getInputType();
+ int paramCount = requestParams.getLogical().size();
+ if( paramCount < 1 ) return false;
+ DataType<?> finalParam = requestParams.getLogical().get( paramCount - 1
);
+ if ( finalParam.getPhysical() != ResponseDispatch.class ) return false;
+
+ return true;
+ } // end method isAsyncServerOperation
+
+ static QName ASYNC_INVOCATION = new QName(Constants.SCA11_NS,
"asyncInvocation");
+ /**
+ * Indicates if this interface is an Async Server interface
+ * @return true if the interface is Async Server, false otherwise
+ */
+ private boolean isAsyncServer() {
+
+ List<Intent> intents = getRequiredIntents();
+ for( Intent intent: intents ) {
+ if ( intent.getName().equals(ASYNC_INVOCATION) ) {
+ return true;
+ }
+ } // end for
+ return false;
+ } // end method isAsyncServer
}
Modified:
tuscany/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceIntrospectorImpl.java
URL:
http://svn.apache.org/viewvc/tuscany/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceIntrospectorImpl.java?rev=957877&r1=957876&r2=957877&view=diff
==============================================================================
---
tuscany/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceIntrospectorImpl.java
(original)
+++
tuscany/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceIntrospectorImpl.java
Fri Jun 25 10:21:28 2010
@@ -51,6 +51,7 @@ import org.apache.tuscany.sca.interfaced
import
org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceVisitor;
import org.apache.tuscany.sca.interfacedef.util.JavaXMLMapper;
import org.apache.tuscany.sca.interfacedef.util.XMLType;
+import org.oasisopen.sca.annotation.AsyncFault;
import org.oasisopen.sca.annotation.OneWay;
import org.oasisopen.sca.annotation.Remotable;
@@ -199,6 +200,11 @@ public class JavaInterfaceIntrospectorIm
getActualTypes(method.getGenericParameterTypes(),
method.getParameterTypes(), typeBindings);
Class<?>[] faultTypes =
getActualTypes(method.getGenericExceptionTypes(),
method.getExceptionTypes(), typeBindings);
+
+ // For async server interfaces, faults are described using the
@AsyncFaults annotation
+ if( method.isAnnotationPresent(AsyncFault.class) ) {
+ faultTypes = readAsyncFaultTypes( method );
+ } // end if
boolean nonBlocking = method.isAnnotationPresent(OneWay.class);
if (nonBlocking) {
@@ -256,6 +262,17 @@ public class JavaInterfaceIntrospectorIm
}
return operations;
}
+
+ /**
+ * Reads the fault types declared in an @AsyncFault annotation on an async
server method
+ * @param method - the Method
+ * @return - an array of fault/exception classes
+ */
+ private Class<?>[] readAsyncFaultTypes( Method method ) {
+ AsyncFault theFaults = method.getAnnotation(AsyncFault.class);
+ if ( theFaults == null ) return null;
+ return theFaults.value();
+ } // end method readAsyncFaultTypes
private boolean jaxwsAsyncMethod(Method method) {
if (method.getName().endsWith("Async")) {
Modified:
tuscany/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceUtil.java
URL:
http://svn.apache.org/viewvc/tuscany/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceUtil.java?rev=957877&r1=957876&r2=957877&view=diff
==============================================================================
---
tuscany/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceUtil.java
(original)
+++
tuscany/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceUtil.java
Fri Jun 25 10:21:28 2010
@@ -27,6 +27,7 @@ import java.util.List;
import org.apache.tuscany.sca.interfacedef.DataType;
import org.apache.tuscany.sca.interfacedef.Interface;
import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterface;
import org.apache.tuscany.sca.interfacedef.java.JavaOperation;
/**
@@ -54,7 +55,12 @@ public final class JavaInterfaceUtil {
public static Method findMethod(Class<?> implClass, Operation operation)
throws NoSuchMethodException {
String name = operation.getName();
if (operation instanceof JavaOperation) {
- name = ((JavaOperation)operation).getJavaMethod().getName();
+ if( ((JavaOperation)operation).isAsyncServer() ) {
+ // In this case, the operation is a mapped async server
style method and needs special handling
+ return findAsyncServerMethod( implClass,
(JavaOperation)operation );
+ } else {
+ name =
((JavaOperation)operation).getJavaMethod().getName();
+ } // end if
}
Interface interface1 = operation.getInterface();
int numParams = operation.getInputType().getLogical().size();
@@ -85,6 +91,49 @@ public final class JavaInterfaceUtil {
Class<?>[] paramTypes = getPhysicalTypes(operation);
return implClass.getMethod(name, paramTypes);
}
+
+ /**
+ * Return the method on the implementation class that matches the async
server version of the operation.
+ *
+ * @param implClass the implementation class or interface
+ * @param operation the operation to match - this is the sync equivalent
of an async server operation
+ * @return the method described by the operation
+ * @throws NoSuchMethodException if no such method exists
+ */
+ public static Method findAsyncServerMethod(Class<?> implClass,
JavaOperation operation) throws NoSuchMethodException {
+ String name = operation.getJavaMethod().getName();
+ List<Operation> actualOps = (List<Operation>)
operation.getInterface().getAttributes().get("ASYNC-SERVER-OPERATIONS");
+ Operation matchingOp = null;
+ for( Operation op: actualOps ) {
+ if( op.getName().equals(name) ) {
+ matchingOp = op;
+ break;
+ }
+ } // end for
+ if( matchingOp == null ) throw new NoSuchMethodException("No matching
async method for operation " + operation.getName());
+
+ int numParams = matchingOp.getInputType().getLogical().size();
+
+ List<Method> matchingMethods = new ArrayList<Method>();
+ for (Method m : implClass.getMethods()) {
+ if (m.getName().equals(name) && m.getParameterTypes().length ==
(numParams) ) {
+ matchingMethods.add(m);
+ }
+ }
+
+ if (matchingMethods.size() == 1) {
+ return matchingMethods.get(0);
+ }
+ if (matchingMethods.size() > 1) {
+ Class<?>[] paramTypes = getPhysicalTypes(matchingOp);
+ return implClass.getMethod(name, paramTypes);
+ }
+
+ // No matching method found
+ throw new NoSuchMethodException("No matching method for operation " +
operation.getName()
+ + " is found on " + implClass);
+
+ } // end method findAsyncServerMethod
/**
* @Deprecated
Modified:
tuscany/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaOperationImpl.java
URL:
http://svn.apache.org/viewvc/tuscany/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaOperationImpl.java?rev=957877&r1=957876&r2=957877&view=diff
==============================================================================
---
tuscany/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaOperationImpl.java
(original)
+++
tuscany/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaOperationImpl.java
Fri Jun 25 10:21:28 2010
@@ -33,6 +33,7 @@ public class JavaOperationImpl extends O
private Method method;
private String action;
+ private boolean isAsyncServer = false;
public Method getJavaMethod() {
return method;
@@ -74,6 +75,22 @@ public class JavaOperationImpl extends O
return false;
return true;
}
+
+ /**
+ * Sets whether this operation has async server style
+ * @param isAsync - "true" marks this operation as async server style
+ */
+ public void setAsyncServer( boolean isAsync ) {
+ isAsyncServer = isAsync;
+ }
+
+ /**
+ * Indicates whether this operation is async server style
+ * @return - true if the operation is async server style
+ */
+ public boolean isAsyncServer() {
+ return isAsyncServer;
+ }
@Override
public String toString() {