diff options
author | slaws <slaws@13f79535-47bb-0310-9956-ffa450edef68> | 2009-04-30 12:29:50 +0000 |
---|---|---|
committer | slaws <slaws@13f79535-47bb-0310-9956-ffa450edef68> | 2009-04-30 12:29:50 +0000 |
commit | 34766b4b32027392eb927557cdb6230061803e7c (patch) | |
tree | a64214a0e0c9bbb3bdbdc4f0b0dd941d33f3f0b6 /branches/sca-java-1.x/modules/binding-jms-runtime | |
parent | 1936c49187913656f82d289f5e72bdf536c142bf (diff) |
TUSCANY-2996 - Add support for wrapSingle attribute that, when set true, ensures that single parameters are wrapped in an array on the wire. When set false single parameters will not be wrapped on the wire. Multiple parameters will always be wrapped.
git-svn-id: http://svn.us.apache.org/repos/asf/tuscany@770201 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'branches/sca-java-1.x/modules/binding-jms-runtime')
5 files changed, 236 insertions, 23 deletions
diff --git a/branches/sca-java-1.x/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/ObjectMessageProcessor.java b/branches/sca-java-1.x/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/ObjectMessageProcessor.java index 97d3d861f4..331c63f20f 100644 --- a/branches/sca-java-1.x/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/ObjectMessageProcessor.java +++ b/branches/sca-java-1.x/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/ObjectMessageProcessor.java @@ -34,7 +34,6 @@ import org.osoa.sca.ServiceRuntimeException; /** * MessageProcessor for sending/receiving Serializable objects with the JMSBinding. * - * @version $Rev$ $Date$ */ public class ObjectMessageProcessor extends AbstractMessageProcessor { private static final Logger logger = Logger.getLogger(ObjectMessageProcessor.class.getName()); @@ -44,17 +43,6 @@ public class ObjectMessageProcessor extends AbstractMessageProcessor { } @Override - protected Object extractPayload(Message msg) { - try { - - return ((ObjectMessage)msg).getObject(); - - } catch (JMSException e) { - throw new JMSBindingException(e); - } - } - - @Override protected Message createJMSMessage(Session session, Object o) { if (session == null) { logger.fine("no response session to create message: " + String.valueOf(o)); @@ -96,4 +84,147 @@ public class ObjectMessageProcessor extends AbstractMessageProcessor { return extractPayload(msg); } + @Override + protected Object extractPayload(Message msg) { + try { + + return ((ObjectMessage)msg).getObject(); + + } catch (JMSException e) { + throw new JMSBindingException(e); + } + } + + // special methods for handling operations with single parameters + + public Message createJMSMessageForSingleParamOperation(Session session, Object o, boolean wrapSingleInput) { + if (session == null) { + logger.fine("no response session to create message: " + String.valueOf(o)); + return null; + } + try { + + ObjectMessage message = session.createObjectMessage(); + + if (o != null) { + if (!(o instanceof Serializable)) { + throw new IllegalStateException("JMS ObjectMessage payload not Serializable: " + o); + } + + // If the user has specifically requests that single parameters + // be wrapped then leave is as is as it will have already been + // wrapped by Tuscany. Otherwise unwrap it. + if (wrapSingleInput) { + message.setObject((Serializable) o); + } else { // unwrap from array + message.setObject((Serializable) ((Object[]) o)[0]); + } + + } + + return message; + + } catch (JMSException e) { + throw new JMSBindingException(e); + } + } + + public Object extractPayloadFromJMSMessageForSingleParamOperation(Message msg, Class<?> argType, boolean wrapSingle) { + // We always have a one arg operation if this method is called so we need to + // decide if the data on the wire is wrapped or not. This is the algorithm. + // + // If the payload is null then create an empty array and pass it on + // If the payload is not an array then it must represent an unwrapped + // single arg. Wrap it up and pass it on + // If the payload is an array then determine if it's a wrapped single arg or not + // If the service interface arg type matches the type of the array and not it's contents + // then it's an unwrapped argument so wrap it and pass it on + // If the service interface arg type matches the type of the contents and not the type + // of the array then the parameter is already wrapped so pass it on as is + // If the service interface arg type matches both the type of the + // array and the type of its contents then assume that the whole array is the + // parameter and decide whether to unwrap it or pass it on as is based on the + // setting of the wrapSingle attribute + // + + try { + Object payload = ((ObjectMessage) msg).getObject(); + + if (payload instanceof Throwable) { + if (payload instanceof RuntimeException) { + throw new ServiceRuntimeException("remote service exception, see nested exception", (RuntimeException) payload); + } else { + return new InvocationTargetException((Throwable) payload); + } + } + + if (payload == null) { + // methodA(null) was not wrapped on wire so wrap it here in order + // that it passes through the rest of the Tuscany wire successfully + return new Object[] { payload }; + } + + boolean payloadIsArray = payload.getClass().isArray(); + + // Non-array payload is single arg + if (!payloadIsArray) { + // methodB(arg) wasn't wrapped on wire so wrap it here in order + // that it passes through the rest of the Tuscany wire successfully + return new Object[] { payload }; + } else { + int size = ((Object[]) payload).length; + + // An initial quick check to determine whether the payload is not + // wrapped. If the array has anything other than a single entry + // then it's not the result of reference side wrapping so wrap it + // here and pass it on + if (size != 1) { + return new Object[] { payload }; + } + + // we know the array has only one entry now so get it + Object arrayContents = ((Object[]) payload)[0]; + + // Is the operation argument the same type as the array itself? + if (argType.isAssignableFrom(payload.getClass())) { + + // So we believe that the whole array is the argument but need + // to check what is in the array to be sure + if (arrayContents == null) { + // There is nothing in the array so it could be an accident that + // the array type matches the argument type, e.g. op(Object) + // so rely on the wrapSingle setting to choose + if (wrapSingle) { + return payload; + } else { + return new Object[] { payload }; + } + } else if (argType.isAssignableFrom(arrayContents.getClass())) { + // We can't tell as the argument type matches both the array type and + // the array contents type so use the wrapSingle setting to choose + if (wrapSingle) { + return payload; + } else { + return new Object[] { payload }; + } + } else { + // So by now we know the whole array is intended to be the + // parameter to wrap it and send it on + return new Object[] { payload }; + } + + } else { + // The array type doesn't match the argument type so assume that the + // array contents will match the argument type and that hence the + // parameter is already wrapped so just send it as is. If the contents + // type doesn't match the argument type a exception will be thrown further + // along the wire + return payload; + } + } + } catch (JMSException e) { + throw new JMSBindingException(e); + } + } + } diff --git a/branches/sca-java-1.x/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/wireformat/jmsobject/runtime/WireFormatJMSObjectReferenceInterceptor.java b/branches/sca-java-1.x/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/wireformat/jmsobject/runtime/WireFormatJMSObjectReferenceInterceptor.java index 6ba62d7681..22c66b0b78 100644 --- a/branches/sca-java-1.x/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/wireformat/jmsobject/runtime/WireFormatJMSObjectReferenceInterceptor.java +++ b/branches/sca-java-1.x/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/wireformat/jmsobject/runtime/WireFormatJMSObjectReferenceInterceptor.java @@ -20,6 +20,8 @@ package org.apache.tuscany.sca.binding.jms.wireformat.jmsobject.runtime; import java.lang.reflect.InvocationTargetException; +import java.util.HashMap; + import javax.jms.JMSException; import javax.jms.Session; @@ -31,6 +33,7 @@ import org.apache.tuscany.sca.binding.jms.impl.JMSBindingException; import org.apache.tuscany.sca.binding.jms.provider.JMSMessageProcessor; import org.apache.tuscany.sca.binding.jms.provider.JMSMessageProcessorUtil; import org.apache.tuscany.sca.binding.jms.provider.JMSResourceFactory; +import org.apache.tuscany.sca.binding.jms.provider.ObjectMessageProcessor; import org.apache.tuscany.sca.binding.jms.wireformat.jmsobject.WireFormatJMSObject; import org.apache.tuscany.sca.invocation.Interceptor; import org.apache.tuscany.sca.invocation.Invoker; @@ -50,13 +53,16 @@ public class WireFormatJMSObjectReferenceInterceptor implements Interceptor { private JMSMessageProcessor requestMessageProcessor; private JMSMessageProcessor responseMessageProcessor; - public WireFormatJMSObjectReferenceInterceptor(JMSBinding jmsBinding, JMSResourceFactory jmsResourceFactory, RuntimeWire runtimeWire) { + private HashMap<String, String> singleArgMap; + + public WireFormatJMSObjectReferenceInterceptor(JMSBinding jmsBinding, JMSResourceFactory jmsResourceFactory, RuntimeWire runtimeWire, HashMap<String, String> hashMap) { super(); this.jmsBinding = jmsBinding; this.runtimeWire = runtimeWire; this.jmsResourceFactory = jmsResourceFactory; this.requestMessageProcessor = JMSMessageProcessorUtil.getRequestMessageProcessor(jmsBinding); this.responseMessageProcessor = JMSMessageProcessorUtil.getResponseMessageProcessor(jmsBinding); + this.singleArgMap = hashMap; } public Message invoke(Message msg) { @@ -78,8 +84,27 @@ public class WireFormatJMSObjectReferenceInterceptor implements Interceptor { // get the jms context JMSBindingContext context = msg.getBindingContext(); Session session = context.getJmsSession(); - - javax.jms.Message requestMsg = requestMessageProcessor.insertPayloadIntoJMSMessage(session, msg.getBody()); + + javax.jms.Message requestMsg; + + // Tuscany automatically wraps operation arguments in an array before we + // get to this point so here we need to decide how they are going to appear + // on the wire. + // + // If the operation has a single parameter and the user has set @wrapSingle=false + // then + // send the single parameter out onto the wire unwrapped + // else + // send out the message as is + // + if (singleArgMap.get(msg.getOperation().getName()) == null) { + requestMsg = requestMessageProcessor.insertPayloadIntoJMSMessage(session, msg.getBody()); + } else { + // we know that wrapSinle is set to false here as the provider only + // populates singleArgMap if it is set false + requestMsg = ((ObjectMessageProcessor) requestMessageProcessor).createJMSMessageForSingleParamOperation(session, msg.getBody(), false); + } + msg.setBody(requestMsg); requestMsg.setJMSReplyTo(context.getReplyToDestination()); diff --git a/branches/sca-java-1.x/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/wireformat/jmsobject/runtime/WireFormatJMSObjectReferenceProvider.java b/branches/sca-java-1.x/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/wireformat/jmsobject/runtime/WireFormatJMSObjectReferenceProvider.java index 644c9ebc38..702293301b 100644 --- a/branches/sca-java-1.x/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/wireformat/jmsobject/runtime/WireFormatJMSObjectReferenceProvider.java +++ b/branches/sca-java-1.x/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/wireformat/jmsobject/runtime/WireFormatJMSObjectReferenceProvider.java @@ -19,12 +19,16 @@ package org.apache.tuscany.sca.binding.jms.wireformat.jmsobject.runtime; +import java.util.HashMap; +import java.util.List; + import org.apache.tuscany.sca.assembly.Binding; import org.apache.tuscany.sca.binding.jms.impl.JMSBinding; import org.apache.tuscany.sca.binding.jms.impl.JMSBindingConstants; import org.apache.tuscany.sca.binding.jms.wireformat.jmsobject.WireFormatJMSObject; import org.apache.tuscany.sca.core.ExtensionPointRegistry; import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.Operation; import org.apache.tuscany.sca.invocation.Interceptor; import org.apache.tuscany.sca.invocation.Phase; import org.apache.tuscany.sca.provider.WireFormatProvider; @@ -40,6 +44,8 @@ public class WireFormatJMSObjectReferenceProvider implements WireFormatProvider private RuntimeComponentReference reference; private JMSBinding binding; private InterfaceContract interfaceContract; + + private HashMap<String,String> singleArgMap; //map of one arg operations, leave empty if wrapSingleInput is true public WireFormatJMSObjectReferenceProvider(ExtensionPointRegistry registry, RuntimeComponent component, @@ -51,6 +57,8 @@ public class WireFormatJMSObjectReferenceProvider implements WireFormatProvider this.reference = reference; this.binding = (JMSBinding)binding; + this.singleArgMap = new HashMap<String,String>(); + // configure the reference based on this wire format // currently maintaining the message processor structure which @@ -58,10 +66,21 @@ public class WireFormatJMSObjectReferenceProvider implements WireFormatProvider // any message processors specified in the SCDL in this case if (this.binding.getRequestWireFormat() instanceof WireFormatJMSObject){ this.binding.setRequestMessageProcessorName(JMSBindingConstants.OBJECT_MP_CLASSNAME); + + //we don't need to create this map if wrapSingleInput is true + if (!((WireFormatJMSObject) this.binding.getRequestWireFormat()).isWrappedSingleInput()){ + List<Operation> opList = reference.getReference().getInterfaceContract().getInterface().getOperations(); + + for (Operation op: opList) { + if (op.getInputType().getLogical().size() == 1){ + this.singleArgMap.put(op.getName(), ""); + } + } + } } if (this.binding.getResponseWireFormat() instanceof WireFormatJMSObject){ this.binding.setResponseMessageProcessorName(JMSBindingConstants.OBJECT_MP_CLASSNAME); - } + } // just point to the reference interface contract so no // databinding transformation takes place @@ -87,7 +106,7 @@ public class WireFormatJMSObjectReferenceProvider implements WireFormatProvider public Interceptor createInterceptor() { return new WireFormatJMSObjectReferenceInterceptor(binding, null, - reference.getRuntimeWire(binding)); + reference.getRuntimeWire(binding), this.singleArgMap); } public String getPhase() { diff --git a/branches/sca-java-1.x/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/wireformat/jmsobject/runtime/WireFormatJMSObjectServiceInterceptor.java b/branches/sca-java-1.x/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/wireformat/jmsobject/runtime/WireFormatJMSObjectServiceInterceptor.java index b063f8d53b..5979bc9214 100644 --- a/branches/sca-java-1.x/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/wireformat/jmsobject/runtime/WireFormatJMSObjectServiceInterceptor.java +++ b/branches/sca-java-1.x/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/wireformat/jmsobject/runtime/WireFormatJMSObjectServiceInterceptor.java @@ -18,6 +18,8 @@ */ package org.apache.tuscany.sca.binding.jms.wireformat.jmsobject.runtime; +import java.util.HashMap; + import javax.jms.Session; import org.apache.tuscany.sca.binding.jms.context.JMSBindingContext; @@ -25,6 +27,7 @@ import org.apache.tuscany.sca.binding.jms.impl.JMSBinding; import org.apache.tuscany.sca.binding.jms.provider.JMSMessageProcessor; import org.apache.tuscany.sca.binding.jms.provider.JMSMessageProcessorUtil; import org.apache.tuscany.sca.binding.jms.provider.JMSResourceFactory; +import org.apache.tuscany.sca.binding.jms.provider.ObjectMessageProcessor; import org.apache.tuscany.sca.binding.jms.wireformat.jmsobject.WireFormatJMSObject; import org.apache.tuscany.sca.interfacedef.Operation; import org.apache.tuscany.sca.invocation.Interceptor; @@ -45,14 +48,19 @@ public class WireFormatJMSObjectServiceInterceptor implements Interceptor { private JMSBinding jmsBinding; private JMSMessageProcessor requestMessageProcessor; private JMSMessageProcessor responseMessageProcessor; + private HashMap<String,Class<?>> singleArgMap; + private boolean wrapSingle; - public WireFormatJMSObjectServiceInterceptor(JMSBinding jmsBinding, JMSResourceFactory jmsResourceFactory, RuntimeWire runtimeWire) { + public WireFormatJMSObjectServiceInterceptor(JMSBinding jmsBinding, JMSResourceFactory jmsResourceFactory, + RuntimeWire runtimeWire, HashMap<String, Class<?>> singleArgMap, boolean wrapSingle) { super(); this.jmsBinding = jmsBinding; this.runtimeWire = runtimeWire; this.jmsResourceFactory = jmsResourceFactory; this.requestMessageProcessor = JMSMessageProcessorUtil.getRequestMessageProcessor(jmsBinding); this.responseMessageProcessor = JMSMessageProcessorUtil.getResponseMessageProcessor(jmsBinding); + this.singleArgMap = singleArgMap; + this.wrapSingle = wrapSingle; } public Message invoke(Message msg) { @@ -79,8 +87,18 @@ public class WireFormatJMSObjectServiceInterceptor implements Interceptor { // get the jms context JMSBindingContext context = msg.getBindingContext(); javax.jms.Message jmsMsg = context.getJmsMsg(); - - Object requestPayload = requestMessageProcessor.extractPayloadFromJMSMessage(jmsMsg); + Object requestPayload; + + // If the service interface has a single argument then we need + // to check if the object from the wire is expected + // to be unwrapped or not + // + Class<?> argType = this.singleArgMap.get(msg.getOperation().getName()); + if (argType == null) { + requestPayload = requestMessageProcessor.extractPayloadFromJMSMessage(jmsMsg); + }else { + requestPayload = ((ObjectMessageProcessor)requestMessageProcessor).extractPayloadFromJMSMessageForSingleParamOperation(jmsMsg, argType, wrapSingle); + } if (requestPayload != null && requestPayload.getClass().isArray()) { msg.setBody(requestPayload); diff --git a/branches/sca-java-1.x/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/wireformat/jmsobject/runtime/WireFormatJMSObjectServiceProvider.java b/branches/sca-java-1.x/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/wireformat/jmsobject/runtime/WireFormatJMSObjectServiceProvider.java index e5887ec1b7..dc4726f4b7 100644 --- a/branches/sca-java-1.x/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/wireformat/jmsobject/runtime/WireFormatJMSObjectServiceProvider.java +++ b/branches/sca-java-1.x/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/wireformat/jmsobject/runtime/WireFormatJMSObjectServiceProvider.java @@ -20,12 +20,16 @@ package org.apache.tuscany.sca.binding.jms.wireformat.jmsobject.runtime; +import java.util.HashMap; +import java.util.List; + import org.apache.tuscany.sca.assembly.Binding; import org.apache.tuscany.sca.binding.jms.impl.JMSBinding; import org.apache.tuscany.sca.binding.jms.impl.JMSBindingConstants; import org.apache.tuscany.sca.binding.jms.wireformat.jmsobject.WireFormatJMSObject; import org.apache.tuscany.sca.core.ExtensionPointRegistry; import org.apache.tuscany.sca.interfacedef.InterfaceContract; +import org.apache.tuscany.sca.interfacedef.Operation; import org.apache.tuscany.sca.invocation.Interceptor; import org.apache.tuscany.sca.invocation.Phase; import org.apache.tuscany.sca.provider.WireFormatProvider; @@ -41,6 +45,8 @@ public class WireFormatJMSObjectServiceProvider implements WireFormatProvider { private RuntimeComponentService service; private JMSBinding binding; private InterfaceContract interfaceContract; + private HashMap<String,Class<?>> singleArgMap; + private boolean wrapSingle = true; public WireFormatJMSObjectServiceProvider(ExtensionPointRegistry registry, RuntimeComponent component, @@ -51,6 +57,7 @@ public class WireFormatJMSObjectServiceProvider implements WireFormatProvider { this.component = component; this.service = service; this.binding = (JMSBinding)binding; + this.singleArgMap = new HashMap<String,Class<?>>(); // configure the service based on this wire format @@ -59,6 +66,17 @@ public class WireFormatJMSObjectServiceProvider implements WireFormatProvider { // any message processors specified in the SCDL in this case if (this.binding.getRequestWireFormat() instanceof WireFormatJMSObject){ this.binding.setRequestMessageProcessorName(JMSBindingConstants.OBJECT_MP_CLASSNAME); + + List<Operation> opList = service.getService().getInterfaceContract().getInterface().getOperations(); + + for (Operation op: opList) { + if (op.getInputType().getLogical().size() == 1){ + this.singleArgMap.put(op.getName(), op.getInputType().getLogical().get(0).getPhysical()); + } + } + + wrapSingle = ((WireFormatJMSObject) this.binding.getRequestWireFormat()).isWrappedSingleInput(); + } if (this.binding.getResponseWireFormat() instanceof WireFormatJMSObject){ this.binding.setResponseMessageProcessorName(JMSBindingConstants.OBJECT_MP_CLASSNAME); @@ -67,6 +85,8 @@ public class WireFormatJMSObjectServiceProvider implements WireFormatProvider { // just point to the reference interface contract so no // databinding transformation takes place interfaceContract = service.getInterfaceContract(); + + } public InterfaceContract configureWireFormatInterfaceContract(InterfaceContract interfaceContract){ @@ -88,9 +108,9 @@ public class WireFormatJMSObjectServiceProvider implements WireFormatProvider { /** */ public Interceptor createInterceptor() { - return new WireFormatJMSObjectServiceInterceptor((JMSBinding)binding, - null, - service.getRuntimeWire(binding)); + + return new WireFormatJMSObjectServiceInterceptor((JMSBinding)binding, null,service.getRuntimeWire(binding), + this.singleArgMap, wrapSingle ); } /** |