summaryrefslogtreecommitdiffstats
path: root/branches
diff options
context:
space:
mode:
authorbeckerdo <beckerdo@13f79535-47bb-0310-9956-ffa450edef68>2009-01-11 22:14:15 +0000
committerbeckerdo <beckerdo@13f79535-47bb-0310-9956-ffa450edef68>2009-01-11 22:14:15 +0000
commit06411d4f4afcb69eafa24cadad267eb6681ddaa2 (patch)
tree11847614377caa655975d65becf85a2f79eb4fa6 /branches
parent77e0d936ff50694b2c450ab74a4490f2462bc93f (diff)
TUSCANY-2332 Web services Holder support
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@733526 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'branches')
-rw-r--r--branches/sca-java-1.x/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/DataTransformationInterceptor.java52
-rw-r--r--branches/sca-java-1.x/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/JDKInvocationHandler.java86
-rw-r--r--branches/sca-java-1.x/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationInvoker.java89
-rw-r--r--branches/sca-java-1.x/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceIntrospectorImpl.java43
-rw-r--r--branches/sca-java-1.x/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/impl/DataTypeImpl.java24
5 files changed, 279 insertions, 15 deletions
diff --git a/branches/sca-java-1.x/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/DataTransformationInterceptor.java b/branches/sca-java-1.x/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/DataTransformationInterceptor.java
index 5814f3d215..ee26d61c42 100644
--- a/branches/sca-java-1.x/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/DataTransformationInterceptor.java
+++ b/branches/sca-java-1.x/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/DataTransformationInterceptor.java
@@ -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.DataType;
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 @@ public class DataTransformationInterceptor implements Interceptor, DataExchangeS
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 class DataTransformationInterceptor implements Interceptor, DataExchangeS
}
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 @@ public class DataTransformationInterceptor implements Interceptor, DataExchangeS
}
} 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 @@ public class DataTransformationInterceptor implements Interceptor, DataExchangeS
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;
+ }
}
diff --git a/branches/sca-java-1.x/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/JDKInvocationHandler.java b/branches/sca-java-1.x/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/JDKInvocationHandler.java
index a23b9af9ad..4216217028 100644
--- a/branches/sca-java-1.x/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/JDKInvocationHandler.java
+++ b/branches/sca-java-1.x/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/JDKInvocationHandler.java
@@ -23,6 +23,8 @@ import java.io.Serializable;
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.ConversationEndedException;
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 @@ public class JDKInvocationHandler implements InvocationHandler, Serializable {
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 @@ public class JDKInvocationHandler implements InvocationHandler, Serializable {
}
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 @@ public class JDKInvocationHandler implements InvocationHandler, Serializable {
}
+
+ /**
+ * 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;
+ }
+
+
}
diff --git a/branches/sca-java-1.x/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationInvoker.java b/branches/sca-java-1.x/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationInvoker.java
index 25d538cff4..1ce4643ccd 100644
--- a/branches/sca-java-1.x/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationInvoker.java
+++ b/branches/sca-java-1.x/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationInvoker.java
@@ -20,6 +20,10 @@ package org.apache.tuscany.sca.implementation.java.invocation;
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 @@ public class JavaImplementationInvoker implements Invoker, DataExchangeSemantics
@SuppressWarnings("unchecked")
public Message invoke(Message msg) {
+ int argumentHolderCount = 0;
Operation op = msg.getOperation();
if (op == null) {
op = this.operation;
@@ -125,6 +130,31 @@ public class JavaImplementationInvoker implements Invoker, DataExchangeSemantics
}
}
+ // 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 @@ public class JavaImplementationInvoker implements Invoker, DataExchangeSemantics
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 @@ public class JavaImplementationInvoker implements Invoker, DataExchangeSemantics
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;
+ }
}
diff --git a/branches/sca-java-1.x/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceIntrospectorImpl.java b/branches/sca-java-1.x/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceIntrospectorImpl.java
index 126b435989..fe99adccec 100644
--- a/branches/sca-java-1.x/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceIntrospectorImpl.java
+++ b/branches/sca-java-1.x/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceIntrospectorImpl.java
@@ -224,14 +224,26 @@ public class JavaInterfaceIntrospectorImpl {
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 @@ public class JavaInterfaceIntrospectorImpl {
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;
+ }
}
diff --git a/branches/sca-java-1.x/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/impl/DataTypeImpl.java b/branches/sca-java-1.x/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/impl/DataTypeImpl.java
index c1c8400b71..8fa91a8e52 100644
--- a/branches/sca-java-1.x/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/impl/DataTypeImpl.java
+++ b/branches/sca-java-1.x/modules/interface/src/main/java/org/apache/tuscany/sca/interfacedef/impl/DataTypeImpl.java
@@ -149,13 +149,6 @@ public class DataTypeImpl<L> implements DataType<L> {
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 @@ public class DataTypeImpl<L> implements DataType<L> {
}
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();
+ }
}