diff options
Diffstat (limited to '')
-rw-r--r-- | sca-java-2.x/tags/2.0-Beta1-RC2/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/ObjectMessageProcessor.java | 231 |
1 files changed, 231 insertions, 0 deletions
diff --git a/sca-java-2.x/tags/2.0-Beta1-RC2/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/ObjectMessageProcessor.java b/sca-java-2.x/tags/2.0-Beta1-RC2/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/ObjectMessageProcessor.java new file mode 100644 index 0000000000..db0b94dce1 --- /dev/null +++ b/sca-java-2.x/tags/2.0-Beta1-RC2/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/ObjectMessageProcessor.java @@ -0,0 +1,231 @@ +/* + * 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.binding.jms.provider; + +import java.io.Serializable; +import java.lang.reflect.InvocationTargetException; +import java.util.logging.Logger; + +import javax.jms.JMSException; +import javax.jms.Message; +import javax.jms.ObjectMessage; +import javax.jms.Session; + +import org.apache.tuscany.sca.binding.jms.JMSBinding; +import org.apache.tuscany.sca.binding.jms.JMSBindingException; +import org.apache.tuscany.sca.core.ExtensionPointRegistry; +import org.oasisopen.sca.ServiceRuntimeException; + +/** + * MessageProcessor for sending/receiving Serializable objects with the JMSBinding. + * + */ +public class ObjectMessageProcessor extends AbstractMessageProcessor { + private static final Logger logger = Logger.getLogger(ObjectMessageProcessor.class.getName()); + + public ObjectMessageProcessor(JMSBinding jmsBinding, ExtensionPointRegistry registry) { + super(jmsBinding); + } + + @Override + protected Message createJMSMessage(Session session, Object o) { + 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); + } + + message.setObject((Serializable)o); + } + + return message; + + } catch (JMSException e) { + throw new JMSBindingException(e); + } + } + + @Override + public Object extractPayloadFromJMSMessage(Message msg) { + try { + Object o = ((ObjectMessage)msg).getObject(); + if (o instanceof Throwable ) { + if (o instanceof RuntimeException) { + throw new ServiceRuntimeException("remote service exception, see nested exception", (RuntimeException)o); + } else { + return new InvocationTargetException((Throwable) o); + } + } + } catch (JMSException e) { + throw new JMSBindingException(e); + } + 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); + } + } + +} |