diff options
10 files changed, 301 insertions, 25 deletions
diff --git a/sca-java-2.x/trunk/modules/assembly/src/main/java/org/apache/tuscany/sca/interfacedef/Operation.java b/sca-java-2.x/trunk/modules/assembly/src/main/java/org/apache/tuscany/sca/interfacedef/Operation.java index c71225c9e2..71c641fa38 100644 --- a/sca-java-2.x/trunk/modules/assembly/src/main/java/org/apache/tuscany/sca/interfacedef/Operation.java +++ b/sca-java-2.x/trunk/modules/assembly/src/main/java/org/apache/tuscany/sca/interfacedef/Operation.java @@ -201,4 +201,9 @@ public interface Operation extends Cloneable, PolicySubject { */ Object clone() throws CloneNotSupportedException; + /** + * Returns the ParameterModes + * @return + */ + List<ParameterMode> getParameterModes(); } diff --git a/sca-java-2.x/trunk/modules/assembly/src/main/java/org/apache/tuscany/sca/interfacedef/ParameterMode.java b/sca-java-2.x/trunk/modules/assembly/src/main/java/org/apache/tuscany/sca/interfacedef/ParameterMode.java new file mode 100644 index 0000000000..c4244a3480 --- /dev/null +++ b/sca-java-2.x/trunk/modules/assembly/src/main/java/org/apache/tuscany/sca/interfacedef/ParameterMode.java @@ -0,0 +1,28 @@ +/*
+ * 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.
+ */
+
+package org.apache.tuscany.sca.interfacedef;
+
+/**
+ * Parameter mode
+ * @see http://java.sun.com/javase/6/docs/api/javax/jws/WebParam.Mode.html
+ */
+public enum ParameterMode {
+ IN, OUT, INOUT;
+}
diff --git a/sca-java-2.x/trunk/modules/assembly/src/main/java/org/apache/tuscany/sca/interfacedef/impl/DataTypeImpl.java b/sca-java-2.x/trunk/modules/assembly/src/main/java/org/apache/tuscany/sca/interfacedef/impl/DataTypeImpl.java index 12ea22938c..572dd7e356 100644 --- a/sca-java-2.x/trunk/modules/assembly/src/main/java/org/apache/tuscany/sca/interfacedef/impl/DataTypeImpl.java +++ b/sca-java-2.x/trunk/modules/assembly/src/main/java/org/apache/tuscany/sca/interfacedef/impl/DataTypeImpl.java @@ -150,11 +150,18 @@ 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(); + public String toString() { + 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(); } @SuppressWarnings("unchecked") diff --git a/sca-java-2.x/trunk/modules/assembly/src/main/java/org/apache/tuscany/sca/interfacedef/impl/OperationImpl.java b/sca-java-2.x/trunk/modules/assembly/src/main/java/org/apache/tuscany/sca/interfacedef/impl/OperationImpl.java index 606782466d..21debb6ea3 100644 --- a/sca-java-2.x/trunk/modules/assembly/src/main/java/org/apache/tuscany/sca/interfacedef/impl/OperationImpl.java +++ b/sca-java-2.x/trunk/modules/assembly/src/main/java/org/apache/tuscany/sca/interfacedef/impl/OperationImpl.java @@ -29,6 +29,7 @@ import javax.xml.namespace.QName; 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.ParameterMode; import org.apache.tuscany.sca.interfacedef.util.WrapperInfo; import org.apache.tuscany.sca.interfacedef.util.XMLType; import org.apache.tuscany.sca.policy.ExtensionType; @@ -49,6 +50,7 @@ public class OperationImpl implements Operation { private DataType<List<DataType>> inputType; private List<DataType> faultTypes; private Interface interfaze; + private List<ParameterMode> parameterModes = new ArrayList<ParameterMode>(); private boolean nonBlocking; private boolean wrapperStyle; private WrapperInfo wrapper; @@ -279,4 +281,8 @@ public class OperationImpl implements Operation { return false; } + public List<ParameterMode> getParameterModes() { + return this.parameterModes; + } + } diff --git a/sca-java-2.x/trunk/modules/binding-corba-runtime/src/test/java/org/apache/tuscany/sca/binding/corba/testing/service/mocks/TestOperation.java b/sca-java-2.x/trunk/modules/binding-corba-runtime/src/test/java/org/apache/tuscany/sca/binding/corba/testing/service/mocks/TestOperation.java index 27278dd64e..8cfcf7af5c 100644 --- a/sca-java-2.x/trunk/modules/binding-corba-runtime/src/test/java/org/apache/tuscany/sca/binding/corba/testing/service/mocks/TestOperation.java +++ b/sca-java-2.x/trunk/modules/binding-corba-runtime/src/test/java/org/apache/tuscany/sca/binding/corba/testing/service/mocks/TestOperation.java @@ -27,6 +27,7 @@ import javax.xml.namespace.QName; 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.ParameterMode; import org.apache.tuscany.sca.interfacedef.util.WrapperInfo; import org.apache.tuscany.sca.interfacedef.util.XMLType; import org.apache.tuscany.sca.policy.ExtensionType; @@ -174,4 +175,9 @@ public class TestOperation implements Operation { return false; } + public List<ParameterMode> getParameterModes() { + // TODO Auto-generated method stub + return null; + } + } diff --git a/sca-java-2.x/trunk/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/DataTransformationInterceptor.java b/sca-java-2.x/trunk/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/DataTransformationInterceptor.java index de29088c1d..7bf9833d04 100644 --- a/sca-java-2.x/trunk/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/DataTransformationInterceptor.java +++ b/sca-java-2.x/trunk/modules/core-databinding/src/main/java/org/apache/tuscany/sca/core/databinding/wire/DataTransformationInterceptor.java @@ -19,11 +19,16 @@ package org.apache.tuscany.sca.core.databinding.wire; +import java.lang.reflect.Method; +import java.lang.reflect.Type; import java.util.HashMap; +import java.util.List; import java.util.Map; import org.apache.tuscany.sca.databinding.Mediator; +import org.apache.tuscany.sca.interfacedef.DataType; import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.java.JavaOperation; import org.apache.tuscany.sca.invocation.Interceptor; import org.apache.tuscany.sca.invocation.Invoker; import org.apache.tuscany.sca.invocation.Message; @@ -50,6 +55,21 @@ public class DataTransformationInterceptor implements Interceptor { 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.invocable = invocable; } @@ -64,12 +84,14 @@ public class DataTransformationInterceptor implements Interceptor { Object input = mediator.mediateInput(msg.getBody(), sourceOperation, targetOperation, metadata); 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(); + if (resultMsg.isFault()) { Object transformedFault = null; if ((result instanceof Exception) && !(result instanceof RuntimeException)) { @@ -95,4 +117,32 @@ public class DataTransformationInterceptor implements Interceptor { this.next = next; } + /** + * 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/sca-java-2.x/trunk/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKInvocationHandler.java b/sca-java-2.x/trunk/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKInvocationHandler.java index d0095f45ee..03853a2883 100644 --- a/sca-java-2.x/trunk/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKInvocationHandler.java +++ b/sca-java-2.x/trunk/modules/core/src/main/java/org/apache/tuscany/sca/core/invocation/impl/JDKInvocationHandler.java @@ -27,6 +27,8 @@ import java.util.IdentityHashMap; import java.util.List; import java.util.Map; +import javax.xml.ws.Holder; + import org.apache.tuscany.sca.assembly.Endpoint; import org.apache.tuscany.sca.context.ThreadMessageContext; import org.apache.tuscany.sca.core.context.ServiceReferenceExt; @@ -103,12 +105,33 @@ public class JDKInvocationHandler implements InvocationHandler, Serializable { if (chain == null) { throw new IllegalArgumentException("No matching operation is found: " + method); - } - - // send the invocation down the source - Object result = invoke(chain, args, source); + } - return result; + // 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, source); + + // Returned Holder data <T> are placed back in Holder<T>. + boolean holderPattern = false; + Class [] parameters = method.getParameterTypes(); + if ( parameters != null ) { + for ( int i = 0, resultIdx = 0; i < parameters.length; i++ ) { + Class parameterType = parameters[ i ]; + if ( isHolder( parameterType ) ) { + holderPattern = true; + // Pop results and place in holder (demote). + Holder holder = (Holder) args[ i ]; + Object[] resultArray = (Object[])result; + holder.value = resultArray[++resultIdx]; + } + } + } + if ( holderPattern ) + return ((Object[])result)[0]; + else + return result; } /** @@ -307,5 +330,58 @@ public class JDKInvocationHandler implements InvocationHandler, Serializable { public void setCallableReference(ServiceReference<?> callableReference) { this.callableReference = (ServiceReferenceExt<?>)callableReference; } - + + /** + * 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/sca-java-2.x/trunk/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationInvoker.java b/sca-java-2.x/trunk/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationInvoker.java index 13fcfbf413..9eade3ba5c 100644 --- a/sca-java-2.x/trunk/modules/implementation-java-runtime/src/main/java/org/apache/tuscany/sca/implementation/java/invocation/JavaImplementationInvoker.java +++ b/sca-java-2.x/trunk/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.ArrayList; +import java.util.List; + +import javax.xml.ws.Holder; import org.apache.tuscany.sca.assembly.EndpointReference; import org.apache.tuscany.sca.core.factory.ObjectCreationException; @@ -33,6 +37,7 @@ import org.apache.tuscany.sca.implementation.java.introspect.JavaIntrospectionHe import org.apache.tuscany.sca.interfacedef.DataType; import org.apache.tuscany.sca.interfacedef.InterfaceContract; import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.ParameterMode; import org.apache.tuscany.sca.interfacedef.java.JavaInterface; import org.apache.tuscany.sca.interfacedef.java.impl.JavaInterfaceUtil; import org.apache.tuscany.sca.invocation.Invoker; @@ -74,6 +79,7 @@ public class JavaImplementationInvoker implements Invoker { @SuppressWarnings("unchecked") public Message invoke(Message msg) { + Operation op = msg.getOperation(); if (op == null) { op = this.operation; @@ -121,6 +127,30 @@ public class JavaImplementationInvoker implements Invoker { Thread.currentThread().setContextClassLoader(instance.getClass().getClassLoader()); + int argumentHolderCount = 0; + + // Holder pattern. Any payload parameters <T> which are should be in holders are placed in Holder<T>. + // Only check Holder for remotable interfaces + if (imethod != null && op.getInterface().isRemotable()) { + List<DataType> inputTypes = op.getInputType().getLogical(); + for (int i = 0, size = inputTypes.size(); i < size; i++) { + if (ParameterMode.IN != op.getParameterModes().get(i)) { + // Promote array params from [<T>] to [Holder<T>] + Object[] payloadArray = (Object[])payload; + + if ( ParameterMode.INOUT == op.getParameterModes().get(i)) { + Object item = payloadArray[i]; + payloadArray[i] = new Holder(item); + } else { + // Create an empty Holder since we should not pass values for OUT parameters + payloadArray[i] = new Holder(); + } + + argumentHolderCount++; + } + } + } + Object ret; if (payload != null && !payload.getClass().isArray()) { ret = imethod.invoke(instance, payload); @@ -130,7 +160,29 @@ public class JavaImplementationInvoker implements Invoker { scopeContainer.returnWrapper(wrapper, contextId); - msg.setBody(ret); + + if (argumentHolderCount > 0) { + // Holder pattern. Any payload Holder<T> types are returned as the message body. + List<Object> returnArgs = new ArrayList<Object>(); + returnArgs.add(ret); + if (imethod != null) { + Object[] payloadArray = (Object[])payload; + for (int i = 0, size = op.getParameterModes().size(); i < size; i++) { + // System.out.println( "JavaImplementationInvoker.invoke return parameter " + i + " type=" + parameter.getClass().getName() ); + if (ParameterMode.IN != op.getParameterModes().get(i)) { + // Demote array params from Holder<T> to <T>. + Holder<Object> item = (Holder<Object>)payloadArray[i]; + payloadArray[i] = item.value; + returnArgs.add(payloadArray[i]); + } + } + } + + msg.setBody(returnArgs.toArray()); + + } else { + msg.setBody(ret); + } } catch (InvocationTargetException e) { Throwable cause = e.getTargetException(); boolean isChecked = false; @@ -140,8 +192,7 @@ public class JavaImplementationInvoker implements Invoker { msg.setFaultBody(cause); break; } - } - + } if (!isChecked) { if (cause instanceof RuntimeException) { throw (RuntimeException)cause; @@ -186,7 +237,6 @@ public class JavaImplementationInvoker implements Invoker { } } - } - + } } diff --git a/sca-java-2.x/trunk/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/JAXWSJavaInterfaceProcessor.java b/sca-java-2.x/trunk/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/JAXWSJavaInterfaceProcessor.java index f18ea0118f..735f8cf269 100644 --- a/sca-java-2.x/trunk/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/JAXWSJavaInterfaceProcessor.java +++ b/sca-java-2.x/trunk/modules/interface-java-jaxws/src/main/java/org/apache/tuscany/sca/interfacedef/java/jaxws/JAXWSJavaInterfaceProcessor.java @@ -31,14 +31,13 @@ import java.util.List; import javax.jws.Oneway; import javax.jws.WebMethod; import javax.jws.WebParam; +import javax.jws.WebParam.Mode; import javax.jws.WebResult; -import javax.jws.WebService; import javax.jws.soap.SOAPBinding; import javax.jws.soap.SOAPBinding.Style; import javax.xml.namespace.QName; import javax.xml.ws.RequestWrapper; import javax.xml.ws.ResponseWrapper; -import javax.xml.ws.WebServiceProvider; import org.apache.tuscany.sca.core.ExtensionPointRegistry; import org.apache.tuscany.sca.core.FactoryExtensionPoint; @@ -51,14 +50,13 @@ import org.apache.tuscany.sca.interfacedef.DataType; import org.apache.tuscany.sca.interfacedef.FaultExceptionMapper; import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; import org.apache.tuscany.sca.interfacedef.Operation; +import org.apache.tuscany.sca.interfacedef.ParameterMode; import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; import org.apache.tuscany.sca.interfacedef.java.JavaInterface; -import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceContract; import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; import org.apache.tuscany.sca.interfacedef.java.JavaOperation; import org.apache.tuscany.sca.interfacedef.java.introspect.JavaInterfaceVisitor; import org.apache.tuscany.sca.interfacedef.util.ElementInfo; -import org.apache.tuscany.sca.interfacedef.util.JavaXMLMapper; import org.apache.tuscany.sca.interfacedef.util.TypeInfo; import org.apache.tuscany.sca.interfacedef.util.WrapperInfo; import org.apache.tuscany.sca.interfacedef.util.XMLType; @@ -89,10 +87,21 @@ public class JAXWSJavaInterfaceProcessor implements JavaInterfaceVisitor { this.wsdlFactory = factories.getFactory(WSDLFactory.class); } + public JAXWSJavaInterfaceProcessor() { super(); } + private ParameterMode getParameterMode(WebParam.Mode mode) { + if (mode == Mode.INOUT) { + return ParameterMode.INOUT; + } else if (mode == Mode.OUT) { + return ParameterMode.OUT; + } else { + return ParameterMode.IN; + } + } + private static String capitalize(String name) { if (name == null || name.length() == 0) { return name; @@ -173,6 +182,7 @@ public class JAXWSJavaInterfaceProcessor implements JavaInterfaceVisitor { if (logical instanceof XMLType) { ((XMLType)logical).setElementName(element); } + operation.getParameterModes().set(i, getParameterMode(param.mode())); } } WebResult result = method.getAnnotation(WebResult.class); @@ -282,6 +292,9 @@ public class JAXWSJavaInterfaceProcessor implements JavaInterfaceVisitor { type = ((XMLType)logical).getTypeName(); } inputElements.add(new ElementInfo(element, new TypeInfo(type, false, null))); + if (param != null) { + operation.getParameterModes().set(i, getParameterMode(param.mode())); + } } List<ElementInfo> outputElements = new ArrayList<ElementInfo>(); diff --git a/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceIntrospectorImpl.java b/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceIntrospectorImpl.java index de32136abc..12b312ffb7 100644 --- a/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceIntrospectorImpl.java +++ b/sca-java-2.x/trunk/modules/interface-java/src/main/java/org/apache/tuscany/sca/interfacedef/java/impl/JavaInterfaceIntrospectorImpl.java @@ -35,6 +35,7 @@ import java.util.concurrent.Future; import javax.xml.namespace.QName; import javax.xml.ws.AsyncHandler; +import javax.xml.ws.Holder; import javax.xml.ws.Response; import org.apache.tuscany.sca.interfacedef.DataType; @@ -44,6 +45,7 @@ import org.apache.tuscany.sca.interfacedef.InvalidInterfaceException; import org.apache.tuscany.sca.interfacedef.InvalidOperationException; import org.apache.tuscany.sca.interfacedef.Operation; import org.apache.tuscany.sca.interfacedef.OverloadedOperationException; +import org.apache.tuscany.sca.interfacedef.ParameterMode; import org.apache.tuscany.sca.interfacedef.impl.DataTypeImpl; import org.apache.tuscany.sca.interfacedef.java.JavaInterface; import org.apache.tuscany.sca.interfacedef.java.JavaInterfaceFactory; @@ -220,6 +222,9 @@ public class JavaInterfaceIntrospectorImpl { } } + JavaOperation operation = new JavaOperationImpl(); + operation.setName(name); + // Set outputType to null for void XMLType xmlReturnType = new XMLType(new QName(ns, "return"), null); DataType<XMLType> returnDataType = @@ -229,10 +234,24 @@ public class JavaInterfaceIntrospectorImpl { 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)); + XMLType xmlParamType = new XMLType(new QName(ns, "arg" + i), null); + + DataTypeImpl<XMLType> xmlDataType = new DataTypeImpl<XMLType>( + UNKNOWN_DATABINDING, paramType, genericParamTypes[i],xmlParamType); + ParameterMode mode = ParameterMode.IN; + // Holder pattern. Physical types of Holder<T> classes are updated to <T> to aid in transformations. + if ( Holder.class == paramType) { + Type firstActual = getFirstActualType( genericParamTypes[ i ] ); + if ( firstActual != null ) { + xmlDataType.setPhysical( (Class<?>)firstActual ); + mode = ParameterMode.INOUT; + } + } + paramDataTypes.add( xmlDataType); + operation.getParameterModes().add(mode); } + + // Fault types List<DataType> faultDataTypes = new ArrayList<DataType>(faultTypes.length); Type[] genericFaultTypes = method.getGenericExceptionTypes(); if( method.isAnnotationPresent(AsyncFault.class) ) { @@ -254,8 +273,7 @@ public class JavaInterfaceIntrospectorImpl { DataType<List<DataType>> inputType = new DataTypeImpl<List<DataType>>(IDL_INPUT, Object[].class, paramDataTypes); - JavaOperation operation = new JavaOperationImpl(); - operation.setName(name); + operation.setInputType(inputType); operation.setOutputType(returnDataType); operation.setFaultTypes(faultDataTypes); @@ -305,5 +323,22 @@ public class JavaInterfaceIntrospectorImpl { } 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; + } } |