Author: beckerdo
Date: Sun Jan 11 14:14:15 2009
New Revision: 733526

URL: http://svn.apache.org/viewvc?rev=733526&view=rev
Log:
TUSCANY-2332 Web services Holder support

Modified:
    
tuscany/branches/sca-java-1.x/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/DataTransformationInterceptor.java
    
tuscany/branches/sca-java-1.x/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/JDKInvocationHandler.java
    
tuscany/branches/sca-java-1.x/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationInvoker.java
    
tuscany/branches/sca-java-1.x/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceIntrospectorImpl.java
    
tuscany/branches/sca-java-1.x/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/impl/DataTypeImpl.java

Modified: 
tuscany/branches/sca-java-1.x/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/DataTransformationInterceptor.java
URL: 
http://svn.apache.org/viewvc/tuscany/branches/sca-java-1.x/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/DataTransformationInterceptor.java?rev=733526&r1=733525&r2=733526&view=diff
==============================================================================
--- 
tuscany/branches/sca-java-1.x/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/DataTransformationInterceptor.java
 (original)
+++ 
tuscany/branches/sca-java-1.x/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/DataTransformationInterceptor.java
 Sun Jan 11 14:14:15 2009
@@ -20,7 +20,10 @@
 package org.apache.tuscany.sca.core.databinding.wire;
 
 import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.lang.reflect.Type;
 import java.util.HashMap;
+import java.util.List;
 import java.util.Map;
 
 import javax.xml.namespace.QName;
@@ -31,6 +34,7 @@
 import org.apache.tuscany.sca.interfacedef.FaultExceptionMapper;
 import org.apache.tuscany.sca.interfacedef.Operation;
 import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl;
+import org.apache.tuscany.sca.interfacedef.java.JavaOperation;
 import org.apache.tuscany.sca.interfacedef.util.FaultException;
 import org.apache.tuscany.sca.interfacedef.util.XMLType;
 import org.apache.tuscany.sca.invocation.DataExchangeSemantics;
@@ -63,6 +67,21 @@
         super();
         this.sourceOperation = sourceOperation;
         this.targetOperation = targetOperation;
+        if ( sourceOperation instanceof JavaOperation ) {
+            JavaOperation javaOp = (JavaOperation) sourceOperation;
+            Method sourceMethod = javaOp.getJavaMethod();
+        }
+        // Holder pattern. In order to perform data mediation on Holder return 
types, it is
+        // necessary to set up a data transformation on the Holder<T> class T. 
on return.
+        DataType<DataType> returnTargetType = getFirstHolderType( 
sourceOperation.getInputType() );
+        if ( returnTargetType != null ) {
+           this.sourceOperation.setOutputType(returnTargetType);               
+        }
+        returnTargetType = getFirstHolderType( targetOperation.getInputType() 
);
+        if ( returnTargetType != null ) {
+           this.targetOperation.setOutputType(returnTargetType);               
+        }
+        
         this.mediator = mediator;
         this.wire = wire;
         this.faultExceptionMapper = faultExceptionMapper;
@@ -73,15 +92,17 @@
     }
 
     public Message invoke(Message msg) {
+        // System.out.println( "DataTransformationInterceptor.invoke source 
input type=" + sourceOperation.getInputType() );
+        // System.out.println( "DataTransformationInterceptor.invoke target 
input type =" + targetOperation.getInputType() );
         Object input = transform(msg.getBody(), 
sourceOperation.getInputType(), targetOperation.getInputType(), false);
         msg.setBody(input);
         Message resultMsg = next.invoke(msg);
-        Object result = resultMsg.getBody();
         if (sourceOperation.isNonBlocking()) {
             // Not to reset the message body
             return resultMsg;
         }
 
+        Object result = resultMsg.getBody();
         // FIXME: Should we fix the Operation model so that getOutputType
         // returns DataType<DataType<T>>?
         DataType<DataType> targetType =
@@ -164,6 +185,7 @@
             }
 
         } else {
+            // !resultMsg.isFault()
             assert !(result instanceof Throwable) : "Expected messages that 
are not throwable " + result;
 
             Object newResult = transform(result, targetType, sourceType, true);
@@ -261,4 +283,32 @@
         return true;
     }
 
+    /**
+     * Returns return type for first Holder in input list.
+     * Returns null if the inputs do not contain a Holder.
+     */
+    protected static DataType<DataType> getFirstHolderType( 
DataType<List<DataType>> inputTypes ) {
+       if (inputTypes != null) {
+            List<DataType> logicalType = inputTypes.getLogical();
+            if (logicalType != null) {
+                for (int i = 0; i < logicalType.size(); i++) {
+                    DataType dataType = logicalType.get(i);
+                    if (isHolder(dataType.getGenericType())) {
+                        // Fix up output from void to returned data type.
+                        // 
System.out.println("DataTransformationInterceptor.<> source input[" + i + "] is 
Holder, logicalType=" + dataType);
+                        return dataType;
+                    }
+                }
+            }
+        }
+       return null;
+    }
+
+    protected static boolean isHolder( Type type ) {
+        String typeString = type.toString();
+        if ( typeString.startsWith( "javax.xml.ws.Holder" ) ) {
+            return true;
+        }
+        return false;        
+    }
 }

Modified: 
tuscany/branches/sca-java-1.x/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/JDKInvocationHandler.java
URL: 
http://svn.apache.org/viewvc/tuscany/branches/sca-java-1.x/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/JDKInvocationHandler.java?rev=733526&r1=733525&r2=733526&view=diff
==============================================================================
--- 
tuscany/branches/sca-java-1.x/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/JDKInvocationHandler.java
 (original)
+++ 
tuscany/branches/sca-java-1.x/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/JDKInvocationHandler.java
 Sun Jan 11 14:14:15 2009
@@ -23,6 +23,8 @@
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 import java.lang.reflect.Proxy;
+import java.lang.reflect.Type;
+import java.util.Arrays;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
@@ -58,6 +60,10 @@
 import org.osoa.sca.ServiceReference;
 import org.osoa.sca.ServiceRuntimeException;
 
+import java.util.Iterator;
+import javax.xml.ws.Holder;
+
+
 /**
  * @version $Rev$ $Date$
  */
@@ -150,8 +156,24 @@
             throw new IllegalArgumentException("No matching operation is 
found: " + method);
         }
 
-        // send the invocation down the wire
-        Object result = invoke(chain, args, wire, source);
+        // Holder pattern. Items stored in a Holder<T> are promoted to T.
+        // After the invoke, the returned data <T> are placed back in 
Holder<T>.
+        Object [] promotedArgs = promoteHolderArgs( args );
+        
+        Object result = invoke(chain, promotedArgs, wire, source);
+
+        // Returned Holder data <T> are placed back in Holder<T>.
+        Class [] parameters = method.getParameterTypes();
+        if ( parameters != null ) {
+            for ( int i = 0; i < parameters.length; i++ ) {
+               Class parameterType = parameters[ i ];              
+               if ( isHolder( parameterType ) ) {
+                  // Pop results and place in holder (demote).
+                  Holder holder = (Holder) args[ i ]; 
+                  holder.value = result;
+               }            
+            }
+        }
 
         return result;
     }
@@ -272,8 +294,9 @@
         }
         Invoker headInvoker = chain.getHeadInvoker();
         Operation operation = chain.getTargetOperation();
-        msg.setOperation(operation);
-        msg.setBody(args);
+        
+        msg.setOperation(operation);       
+        msg.setBody( args );
 
         Message msgContext = ThreadMessageContext.getMessageContext();
         Object currentConversationID = 
msgContext.getFrom().getReferenceParameters().getConversationID();
@@ -513,4 +536,59 @@
 
     }
 
+    
+    /**
+     * Creates a copy of arguments. Holder<T> values are promoted to T.
+     * Note. It is essential that arg Holders not be destroyed here.
+     * PromotedArgs should not destroy holders. They are used on response 
return.
+     * @param args containing Holders and other objects.
+     * @return Object [] 
+     */
+    protected static Object [] promoteHolderArgs( Object [] args ) {
+       if ( args == null )
+           return args;
+       Object [] promotedArgs = new Object[ args.length ];
+       
+       for ( int i = 0; i < args.length; i++ ) {
+          Object argument = args[ i ];
+          if ( argument != null ) {
+              if ( isHolder( argument ) ) {
+                 promotedArgs[ i ] = ((Holder)argument).value;      
+              } else {
+                 promotedArgs[ i ] = args[ i ];
+              }
+              
+          }
+       }
+       return promotedArgs;
+    }
+
+    /**
+     * Given a Class, tells if it is a Holder by comparing to 
"javax.xml.ws.Holder"
+     * @param testClass
+     * @return boolean whether class is Holder type.
+     */
+    protected static boolean isHolder( Class testClass ) {
+        if ( testClass.getName().startsWith( "javax.xml.ws.Holder" )) {
+            return true;
+        }
+        return false;        
+    }
+
+     
+    /**
+     * Given an Object, tells if it is a Holder by comparing to 
"javax.xml.ws.Holder"
+     * @param testClass
+     * @return boolean stating whether Object is a Holder type.
+     * @author DOB
+     */
+    protected static boolean isHolder( Object object ) {
+        String objectName = object.getClass().getName();
+        if ( object instanceof javax.xml.ws.Holder ) {
+            return true;
+        }
+        return false;        
+    }
+
+
 }

Modified: 
tuscany/branches/sca-java-1.x/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationInvoker.java
URL: 
http://svn.apache.org/viewvc/tuscany/branches/sca-java-1.x/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationInvoker.java?rev=733526&r1=733525&r2=733526&view=diff
==============================================================================
--- 
tuscany/branches/sca-java-1.x/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationInvoker.java
 (original)
+++ 
tuscany/branches/sca-java-1.x/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationInvoker.java
 Sun Jan 11 14:14:15 2009
@@ -20,6 +20,10 @@
 
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
+import java.util.List;
+import java.util.Vector;
+
+import javax.xml.ws.Holder;
 
 import org.apache.tuscany.sca.core.context.InstanceWrapper;
 import org.apache.tuscany.sca.core.scope.Scope;
@@ -68,6 +72,7 @@
 
     @SuppressWarnings("unchecked")
     public Message invoke(Message msg) {
+        int argumentHolderCount = 0;
         Operation op = msg.getOperation();
         if (op == null) {
             op = this.operation;
@@ -125,6 +130,31 @@
                 }
             }
             
+            // Holder pattern. Any payload parameters <T> which are should be 
in holders are placed in Holder<T>.
+            if ( imethod != null) {
+                Class<?> [] params = imethod.getParameterTypes();
+                if ( params != null ) {
+                    for ( int i = 0; i < params.length; i++ ) {
+                        Class<?> parameter = params[ i ];
+                        if ( isHolder( parameter )) {
+                            // System.out.println( 
"JavaImplementationInvoker.invoke parameter " + i + " is Holder. Payload 
isArray=" + (payload != null ? payload.getClass().isArray() : "null" ));
+                            if (payload != null && 
!payload.getClass().isArray()) {
+                                // Promote single param from <T> to Holder<T>
+                                payload = new Holder( payload );               
                
+                            } else {
+                                // Promote array params from [<T>] to 
[Holder<T>]
+                                Object [] payloadArray = (Object[]) payload;
+                                for ( int j = 0; j < payloadArray.length; j++ 
) {
+                                    Object item = payloadArray[ j ];
+                                    payloadArray[ j ] = new Holder( item );
+                                }
+                            }
+                            argumentHolderCount++;
+                        }
+                    }
+                }                
+            }
+            
             Object ret;
             if (payload != null && !payload.getClass().isArray()) {
                 ret = imethod.invoke(instance, payload);
@@ -140,7 +170,52 @@
                 scopeContainer.remove(contextId);
                 parameters.setConversationID(null);
             }
-            msg.setBody(ret);
+            
+            if (argumentHolderCount > 0) {
+                // Holder pattern. Any payload Holder<T> types are returned as 
the message body.
+                List returnArgs = new Vector<Object>();
+                int foundHolders = 0;
+                if ( imethod != null) {
+                    Class<?> [] params = imethod.getParameterTypes();
+                    if ( params != null ) {
+                        for ( int i = 0; i < params.length; i++ ) {
+                            Class<?> parameter = params[ i ];
+                            // System.out.println( 
"JavaImplementationInvoker.invoke return parameter " + i + " type=" + 
parameter.getClass().getName() );
+                            if ( isHolder( parameter )) {
+                                if (payload != null && 
!payload.getClass().isArray()) {
+                                    // Demote params from Holder<T> to <T>.
+                                    Holder<Object> holder = (Holder<Object>) 
payload;
+                                    returnArgs.add( holder.value );
+                                    foundHolders++;
+                                } else {
+                                    // Demote array params from Holder<T> to 
<T>.
+                                    Object [] payloadArray = (Object[]) 
payload;
+                                    for ( int j = 0; j < payloadArray.length; 
j++ ) {
+                                        Holder<Object> item = (Holder<Object>) 
payloadArray[ j ];
+                                        payloadArray[ j ] = item.value;
+                                        returnArgs.add( payloadArray[ j ] );
+                                    }
+                                    foundHolders++;
+                                }
+                            }
+                        }
+                    }                
+                }
+                // Although payload items are returned in a list, currently 
only support 1 return type.
+                if ( returnArgs.size() == 1 ) {
+                    Object value = returnArgs.get( 0 );
+                    if (( value != null ) && ( value.getClass().isArray() )) {
+                       Object [] values = (Object []) value;
+                       if (( values != null ) && ( values.length > 0 )) {
+                          msg.setBody( values[ 0 ] );
+                       }
+                    } else 
+                        msg.setBody(value);                
+                } else 
+                   msg.setBody(returnArgs.toArray());                
+            } else {
+                msg.setBody(ret);
+            }
         } catch (InvocationTargetException e) {
             Throwable cause = e.getTargetException();
             boolean isChecked = false;
@@ -196,4 +271,16 @@
         return allowsPBR;
     }
 
+    /**
+     * Given a Class, tells if it is a Holder by comparing to 
"javax.xml.ws.Holder"
+     * @param testClass
+     * @return
+     * @author DOB
+     */
+    public static boolean isHolder( Class testClass ) {
+        if ( testClass.getName().equals( "javax.xml.ws.Holder" )) {
+            return true;
+        }
+        return false;        
+    }
 }

Modified: 
tuscany/branches/sca-java-1.x/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceIntrospectorImpl.java
URL: 
http://svn.apache.org/viewvc/tuscany/branches/sca-java-1.x/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceIntrospectorImpl.java?rev=733526&r1=733525&r2=733526&view=diff
==============================================================================
--- 
tuscany/branches/sca-java-1.x/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceIntrospectorImpl.java
 (original)
+++ 
tuscany/branches/sca-java-1.x/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceIntrospectorImpl.java
 Sun Jan 11 14:14:15 2009
@@ -224,14 +224,26 @@
             DataType<XMLType> returnDataType =
                 returnType == void.class ? null : new 
DataTypeImpl<XMLType>(UNKNOWN_DATABINDING, returnType, method
                     .getGenericReturnType(), xmlReturnType);
+
+            // Input types
             List<DataType> paramDataTypes = new 
ArrayList<DataType>(parameterTypes.length);
             Type[] genericParamTypes = method.getGenericParameterTypes();
             for (int i = 0; i < parameterTypes.length; i++) {
                 Class paramType = parameterTypes[i];
                 XMLType xmlParamType = new XMLType(new QName(ns, "arg" + i), 
null);
-                paramDataTypes.add(new 
DataTypeImpl<XMLType>(UNKNOWN_DATABINDING, paramType, genericParamTypes[i],
-                                                             xmlParamType));
+                DataTypeImpl<XMLType> xmlDataType = new DataTypeImpl<XMLType>(
+                    UNKNOWN_DATABINDING, paramType, 
genericParamTypes[i],xmlParamType);
+                // Holder pattern. Physical types of Holder<T> classes are 
updated to <T> to aid in transformations.
+                if ( isHolder( paramType )) {
+                    Type firstActual = getFirstActualType( genericParamTypes[ 
i ] );
+                    if ( firstActual != null ) {
+                        xmlDataType.setPhysical( (Class<?>)firstActual );
+                    }
+                }
+                paramDataTypes.add( xmlDataType);
             }
+            
+            // Fault types
             List<DataType> faultDataTypes = new 
ArrayList<DataType>(faultTypes.length);
             Type[] genericFaultTypes = method.getGenericExceptionTypes();
             for (int i = 0; i < faultTypes.length; i++) {
@@ -263,4 +275,31 @@
         return operations;
     }
 
+    /**
+     * Given a Class, tells if it is a Holder by comparing to 
"javax.xml.ws.Holder"
+     * @param testClass
+     * @return boolean whether testClass is Holder type.
+     */
+    protected static boolean isHolder( Class testClass ) {
+        if ( testClass.getName().startsWith( "javax.xml.ws.Holder" )) {
+            return true;
+        }
+        return false;        
+    }
+
+    /**
+     * Given a Class<T>, returns T, otherwise null.
+     * @param testClass
+     * @return
+     */
+    protected static Type getFirstActualType(Type genericType) {
+        if (genericType instanceof ParameterizedType) {
+            ParameterizedType pType = (ParameterizedType)genericType;
+            Type[] actualTypes = pType.getActualTypeArguments();
+            if ((actualTypes != null) && (actualTypes.length > 0)) {
+                return actualTypes[0];
+            }
+        }
+        return null;
+    }
 }

Modified: 
tuscany/branches/sca-java-1.x/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/impl/DataTypeImpl.java
URL: 
http://svn.apache.org/viewvc/tuscany/branches/sca-java-1.x/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/impl/DataTypeImpl.java?rev=733526&r1=733525&r2=733526&view=diff
==============================================================================
--- 
tuscany/branches/sca-java-1.x/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/impl/DataTypeImpl.java
 (original)
+++ 
tuscany/branches/sca-java-1.x/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/impl/DataTypeImpl.java
 Sun Jan 11 14:14:15 2009
@@ -149,13 +149,6 @@
         this.dataBinding = dataBinding;
     }
 
-    @Override
-    public String toString() {
-        StringBuffer sb = new StringBuffer();
-        sb.append(physical).append(" ").append(dataBinding).append(" 
").append(logical);
-        return sb.toString();
-    }
-
     @SuppressWarnings("unchecked")
     @Override
     public Object clone() throws CloneNotSupportedException {
@@ -216,4 +209,21 @@
         }
         metaDataMap.put(type, metaData);
     }
+    
+    @Override
+    public String toString() {
+        // private Class<?> physical;
+        // private Type genericType;
+        // private L logical;
+        // private Map<Class<?>, Object> metaDataMap;
+        StringBuilder b = new StringBuilder( 256 );
+           b.append( "DataType[" );
+           b.append( "dataBinding=" + ((dataBinding==null) ? "null" : 
dataBinding) );
+           b.append( ", genericType=" + ((genericType==null) ? "null" : 
genericType) ); 
+           b.append( ", physical=" + ((physical==null) ? "null" : physical) ); 
+           b.append( ", logical=" + ((logical==null) ? "null" : logical) );
+           b.append( ", metaData size=" + ((metaDataMap==null) ? "0" : 
metaDataMap.size()) );
+           b.append( "]" );
+        return b.toString();
+    }
 }


Reply via email to