diff options
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 ); } /** |