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() {


Reply via email to