summaryrefslogtreecommitdiffstats
path: root/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider
diff options
context:
space:
mode:
Diffstat (limited to 'sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider')
-rw-r--r--sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/AbstractMessageProcessor.java117
-rw-r--r--sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/DefaultJMSResourceFactoryExtensionPoint.java30
-rw-r--r--sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/JMSBindingInvoker.java467
-rw-r--r--sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/JMSBindingListener.java266
-rw-r--r--sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/JMSBindingProviderFactory.java68
-rw-r--r--sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/JMSBindingReferenceBindingProvider.java134
-rw-r--r--sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/JMSBindingServiceBindingProvider.java306
-rw-r--r--sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/JMSMessageProcessor.java55
-rw-r--r--sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/JMSMessageProcessorUtil.java75
-rw-r--r--sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/JMSResourceFactory.java67
-rw-r--r--sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/JMSResourceFactoryExtensionPoint.java28
-rw-r--r--sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/JMSResourceFactoryImpl.java223
-rw-r--r--sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/ObjectMessageProcessor.java75
-rw-r--r--sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/TextMessageProcessor.java68
-rw-r--r--sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/XMLTextMessageProcessor.java90
15 files changed, 2069 insertions, 0 deletions
diff --git a/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/AbstractMessageProcessor.java b/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/AbstractMessageProcessor.java
new file mode 100644
index 0000000000..2fcb07a07f
--- /dev/null
+++ b/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/AbstractMessageProcessor.java
@@ -0,0 +1,117 @@
+/*
+ * 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 javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.ObjectMessage;
+import javax.jms.Session;
+
+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.impl.JMSBindingException;
+import org.osoa.sca.ServiceRuntimeException;
+
+/**
+ * Base MessageProcessor for the JMSBinding.
+ *
+ * @version $Rev$ $Date$
+ */
+public abstract class AbstractMessageProcessor implements JMSMessageProcessor {
+
+ protected String operationPropertyName;
+ protected boolean xmlFormat = true;
+
+ public AbstractMessageProcessor(JMSBinding jmsBinding) {
+ this.operationPropertyName = jmsBinding.getOperationSelectorPropertyName();
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.tuscany.binding.jms.OperationAndDataBinding#getOperationName(javax.jms.Message)
+ */
+ public String getOperationName(Message message) {
+ try {
+
+ return message.getStringProperty(operationPropertyName);
+
+ } catch (JMSException e) {
+ throw new JMSBindingException("Exception retreiving operation name from message", e);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.tuscany.binding.jms.OperationAndDataBinding#setOperationName(javax.jms.Message, java.lang.String)
+ */
+ public void setOperationName(String operationName, Message message) {
+ try {
+
+ message.setStringProperty(operationPropertyName, operationName);
+
+ } catch (JMSException e) {
+ throw new JMSBindingException("Exception setting the operation name on message", e);
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.tuscany.binding.jms.OperationAndDataBinding#extractPayload(javax.jms.Session, java.lang.Object)
+ */
+ public Message insertPayloadIntoJMSMessage(Session session, Object o) {
+ return createJMSMessage(session, o);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.tuscany.binding.jms.OperationAndDataBinding#extractPayload(javax.jms.Message)
+ */
+ public Object extractPayloadFromJMSMessage(Message msg) {
+ try {
+ if (msg.getBooleanProperty(JMSBindingConstants.FAULT_PROPERTY)) {
+ throw new ServiceRuntimeException("remote service exception, see nested exception", (Throwable)((ObjectMessage)msg).getObject());
+ }
+ } catch (JMSException e) {
+ throw new JMSBindingException(e);
+ }
+ return extractPayload(msg);
+ }
+
+ public Message createFaultMessage(Session session, Throwable o) {
+ try {
+
+ ObjectMessage message = session.createObjectMessage();
+ message.setObject(o);
+ message.setBooleanProperty(JMSBindingConstants.FAULT_PROPERTY, true);
+ return message;
+
+ } catch (JMSException e) {
+ throw new JMSBindingException(e);
+ }
+ }
+
+ protected abstract Object[] extractPayload(Message msg);
+
+ protected abstract Message createJMSMessage(Session session, Object o);
+
+}
diff --git a/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/DefaultJMSResourceFactoryExtensionPoint.java b/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/DefaultJMSResourceFactoryExtensionPoint.java
new file mode 100644
index 0000000000..499f69a24b
--- /dev/null
+++ b/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/DefaultJMSResourceFactoryExtensionPoint.java
@@ -0,0 +1,30 @@
+/*
+ * 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 org.apache.tuscany.sca.binding.jms.impl.JMSBinding;
+
+public class DefaultJMSResourceFactoryExtensionPoint implements JMSResourceFactoryExtensionPoint {
+
+ public JMSResourceFactory createJMSResourceFactory(JMSBinding binding) {
+ return new JMSResourceFactoryImpl(binding.getConnectionFactoryName(), binding.getInitialContextFactoryName(), binding.getJndiURL());
+ }
+
+}
diff --git a/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/JMSBindingInvoker.java b/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/JMSBindingInvoker.java
new file mode 100644
index 0000000000..9c5fba5de6
--- /dev/null
+++ b/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/JMSBindingInvoker.java
@@ -0,0 +1,467 @@
+/*
+ * 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.lang.reflect.InvocationTargetException;
+import java.util.List;
+import java.util.Map;
+
+import javax.jms.DeliveryMode;
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.MessageProducer;
+import javax.jms.Session;
+import javax.naming.NamingException;
+import javax.security.auth.Subject;
+
+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.impl.JMSBindingException;
+import org.apache.tuscany.sca.binding.jms.policy.authentication.token.JMSTokenAuthenticationPolicy;
+import org.apache.tuscany.sca.binding.jms.policy.header.JMSHeaderPolicy;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.interfacedef.java.JavaInterface;
+import org.apache.tuscany.sca.invocation.DataExchangeSemantics;
+import org.apache.tuscany.sca.invocation.Invoker;
+import org.apache.tuscany.sca.policy.PolicySet;
+import org.apache.tuscany.sca.policy.PolicySetAttachPoint;
+import org.apache.tuscany.sca.policy.SecurityUtil;
+import org.apache.tuscany.sca.policy.authentication.token.TokenPrincipal;
+import org.apache.tuscany.sca.runtime.ReferenceParameters;
+import org.apache.tuscany.sca.runtime.RuntimeComponentReference;
+import org.apache.tuscany.sca.runtime.RuntimeComponentService;
+import org.osoa.sca.ServiceRuntimeException;
+
+/**
+ * Invoker for the JMS binding.
+ *
+ * @version $Rev$ $Date$
+ */
+public class JMSBindingInvoker implements Invoker, DataExchangeSemantics {
+
+ protected Operation operation;
+ protected String operationName;
+
+ protected JMSBinding jmsBinding;
+ protected JMSResourceFactory jmsResourceFactory;
+ protected JMSMessageProcessor requestMessageProcessor;
+ protected JMSMessageProcessor responseMessageProcessor;
+ protected Destination bindingRequestDest;
+ protected Destination bindingReplyDest;
+ protected RuntimeComponentReference reference;
+ protected JMSTokenAuthenticationPolicy jmsTokenAuthenticationPolicy = null;
+ protected JMSHeaderPolicy jmsHeaderPolicy = null;
+
+ public JMSBindingInvoker(JMSBinding jmsBinding, Operation operation, JMSResourceFactory jmsResourceFactory, RuntimeComponentReference reference) {
+
+ this.operation = operation;
+ operationName = operation.getName();
+
+ this.jmsBinding = jmsBinding;
+ this.jmsResourceFactory = jmsResourceFactory;
+ this.reference = reference;
+ this.requestMessageProcessor = JMSMessageProcessorUtil.getRequestMessageProcessor(jmsBinding);
+ this.responseMessageProcessor = JMSMessageProcessorUtil.getResponseMessageProcessor(jmsBinding);
+
+ // find out which policies are active
+ if (jmsBinding instanceof PolicySetAttachPoint) {
+ List<PolicySet> policySets = ((PolicySetAttachPoint)jmsBinding).getApplicablePolicySets();
+ for (PolicySet ps : policySets) {
+ for (Object p : ps.getPolicies()) {
+ if (JMSTokenAuthenticationPolicy.class.isInstance(p)) {
+ jmsTokenAuthenticationPolicy = (JMSTokenAuthenticationPolicy)p;
+ }else if (JMSTokenAuthenticationPolicy.class.isInstance(p)) {
+ jmsHeaderPolicy = (JMSHeaderPolicy)p;
+ } else {
+ // etc. check for other types of policy being present
+ }
+ }
+ }
+ }
+
+ try {
+
+ bindingRequestDest = lookupDestination();
+ bindingReplyDest = lookupResponseDestination();
+
+ } catch (NamingException e) {
+ throw new JMSBindingException(e);
+ }
+
+ }
+
+ /**
+ * Looks up the Destination Queue for the JMS Binding
+ *
+ * @return The Destination Queue
+ * @throws NamingException Failed to lookup Destination Queue
+ * @throws JMSBindingException Failed to lookup Destination Queue
+ * @see #lookupDestinationQueue(boolean)
+ */
+ protected Destination lookupDestination() throws NamingException, JMSBindingException {
+ return lookupDestinationQueue(false);
+ }
+
+ /**
+ * Looks up the Destination Response Queue for the JMS Binding
+ *
+ * @return The Destination Response Queue
+ * @throws NamingException Failed to lookup Destination Response Queue
+ * @throws JMSBindingException Failed to lookup Destination Response Queue
+ * @see #lookupDestinationQueue(boolean)
+ */
+ protected Destination lookupResponseDestination() throws NamingException, JMSBindingException {
+ return lookupDestinationQueue(true);
+ }
+
+ /**
+ * Looks up the Destination Queue for the JMS Binding.
+ * <p>
+ * What happens in the look up will depend on the create mode specified for the JMS Binding:
+ * <ul>
+ * <li>always - the JMS queue is always created. It is an error if the queue already exists
+ * <li>ifnotexist - the JMS queue is created if it does not exist. It is not an error if the queue already exists
+ * <li>never - the JMS queue is never created. It is an error if the queue does not exist
+ * </ul>
+ * See the SCA JMS Binding specification for more information.
+ * <p>
+ *
+ * @param isReponseQueue <code>true</code> if we are creating a response queue.
+ * <code>false</code> if we are creating a request queue
+ * @return The Destination queue.
+ * @throws NamingException Failed to lookup JMS queue
+ * @throws JMSBindingException Failed to lookup JMS Queue. Probable cause is that
+ * the JMS queue's current existence/non-existence is not compatible with
+ * the create mode specified on the binding
+ */
+ protected Destination lookupDestinationQueue(boolean isReponseQueue) throws NamingException, JMSBindingException {
+ String queueName;
+ String queueType;
+ String qCreateMode;
+
+ if (isReponseQueue) {
+ queueName = jmsBinding.getResponseDestinationName();
+ queueType = "JMS Response Destination ";
+ qCreateMode = jmsBinding.getResponseDestinationCreate();
+ if (JMSBindingConstants.DEFAULT_RESPONSE_DESTINATION_NAME.equals(queueName)) {
+ return null;
+ }
+ } else {
+ queueName = jmsBinding.getDestinationName();
+ queueType = "JMS Destination ";
+ qCreateMode = jmsBinding.getDestinationCreate();
+ }
+
+ Destination dest = jmsResourceFactory.lookupDestination(queueName);
+
+ if (qCreateMode.equals(JMSBindingConstants.CREATE_ALWAYS)) {
+ // In this mode, the queue must not already exist as we are creating it
+ if (dest != null) {
+ throw new JMSBindingException(queueType + queueName
+ + " already exists but has create mode of \""
+ + qCreateMode
+ + "\" while registering binding "
+ + jmsBinding.getName()
+ + " invoker");
+ }
+ // Create the queue
+ dest = jmsResourceFactory.createDestination(queueName);
+
+ } else if (qCreateMode.equals(JMSBindingConstants.CREATE_IF_NOT_EXIST)) {
+ // In this mode, the queue may nor may not exist. It will be created if it does not exist
+ if (dest == null) {
+ dest = jmsResourceFactory.createDestination(queueName);
+ }
+
+ } else if (qCreateMode.equals(JMSBindingConstants.CREATE_NEVER)) {
+ // In this mode, the queue must have already been created.
+ if (dest == null) {
+ throw new JMSBindingException(queueType + queueName
+ + " not found but create mode of \""
+ + qCreateMode
+ + "\" while registering binding "
+ + jmsBinding.getName()
+ + " invoker");
+ }
+ }
+
+ // Make sure we ended up with a queue
+ if (dest == null) {
+ throw new JMSBindingException(queueType + queueName
+ + " not found with create mode of \""
+ + qCreateMode
+ + "\" while registering binding "
+ + jmsBinding.getName()
+ + " invoker");
+ }
+
+ return dest;
+ }
+
+ public org.apache.tuscany.sca.invocation.Message invoke(org.apache.tuscany.sca.invocation.Message tuscanyMsg) {
+ try {
+
+ Object resp = invokeTarget(tuscanyMsg);
+ tuscanyMsg.setBody(resp);
+
+ } catch (InvocationTargetException e) {
+ tuscanyMsg.setFaultBody(e.getCause());
+ } catch (ServiceRuntimeException e) {
+ if (e.getCause() instanceof InvocationTargetException) {
+ if ((e.getCause().getCause() instanceof RuntimeException)) {
+ tuscanyMsg.setFaultBody(e.getCause());
+ } else {
+ tuscanyMsg.setFaultBody(e.getCause().getCause());
+ }
+ } else {
+ tuscanyMsg.setFaultBody(e);
+ }
+ } catch (Throwable e) {
+ tuscanyMsg.setFaultBody(e);
+ }
+ return tuscanyMsg;
+ }
+
+ protected Object invokeTarget(org.apache.tuscany.sca.invocation.Message tuscanyMsg) throws InvocationTargetException {
+ try {
+ Session session = jmsResourceFactory.createSession();
+ try {
+
+ Destination replyToDest = getReplyToDestination(session);
+
+ Message requestMsg = sendRequest(tuscanyMsg, session, replyToDest);
+
+ if (replyToDest == null) {
+ return null;
+ } else {
+ Message replyMsg = receiveReply(session, replyToDest, requestMsg.getJMSMessageID());
+ Object[] response = (Object[])responseMessageProcessor.extractPayloadFromJMSMessage(replyMsg);
+ return (response != null && response.length > 0) ? response[0] : null;
+ }
+
+ } finally {
+ session.close();
+ }
+ } catch (JMSException e) {
+ throw new InvocationTargetException(e);
+ } catch (NamingException e) {
+ throw new InvocationTargetException(e);
+ }
+ }
+
+ protected Destination getReplyToDestination(Session session) throws JMSException, JMSBindingException, NamingException {
+ Destination replyToDest;
+ if (operation.isNonBlocking()) {
+ replyToDest = null;
+ } else {
+ if (bindingReplyDest != null) {
+ replyToDest = bindingReplyDest;
+ } else {
+ replyToDest = session.createTemporaryQueue();
+ }
+ }
+ return replyToDest;
+ }
+
+ protected Message sendRequest(org.apache.tuscany.sca.invocation.Message tuscanyMsg, Session session, Destination replyToDest) throws JMSException, JMSBindingException,
+ NamingException {
+
+ Message requestMsg = requestMessageProcessor.insertPayloadIntoJMSMessage(session, tuscanyMsg.getBody());
+
+ setHeaders(tuscanyMsg, requestMsg);
+
+ requestMsg.setJMSReplyTo(replyToDest);
+
+ Destination requestDest = getRequestDestination(tuscanyMsg, session);
+
+ MessageProducer producer = session.createProducer(requestDest);
+
+ if (jmsBinding.getOperationJMSTimeToLive(operationName) != null) {
+ producer.setTimeToLive(jmsBinding.getOperationJMSTimeToLive(operationName));
+ }
+
+ try {
+ producer.send(requestMsg);
+ } finally {
+ producer.close();
+ }
+ return requestMsg;
+ }
+
+ protected Destination getRequestDestination(org.apache.tuscany.sca.invocation.Message tuscanyMsg, Session session) throws JMSBindingException, NamingException, JMSException {
+ Destination requestDestination;
+ if (reference.isCallback()) {
+ String toURI = tuscanyMsg.getTo().getURI();
+ if (toURI != null && toURI.startsWith("jms:")) {
+ // the msg to uri contains the callback destination name
+ // this is an jms physical name not a jndi name so need to use session.createQueue
+ requestDestination = session.createQueue(toURI.substring(4));
+ } else {
+ requestDestination = lookupDestination();
+ }
+ } else {
+ requestDestination = bindingRequestDest;
+ }
+
+ return requestDestination;
+ }
+
+ protected void setHeaders(org.apache.tuscany.sca.invocation.Message tuscanyMsg, Message jmsMsg) throws JMSException {
+
+ requestMessageProcessor.setOperationName(jmsBinding.getNativeOperationName(operationName), jmsMsg);
+
+ if ((jmsHeaderPolicy != null) &&
+ (jmsHeaderPolicy.getDeliveryModePersistent() != null)) {
+ if (jmsHeaderPolicy.getDeliveryModePersistent()) {
+ jmsMsg.setJMSDeliveryMode(DeliveryMode.PERSISTENT);
+ } else {
+ jmsMsg.setJMSDeliveryMode(DeliveryMode.NON_PERSISTENT);
+ }
+
+ } else if (jmsBinding.getOperationJMSDeliveryMode(operationName) != null) {
+ if (jmsBinding.getOperationJMSDeliveryMode(operationName)) {
+ jmsMsg.setJMSDeliveryMode(DeliveryMode.PERSISTENT);
+ } else {
+ jmsMsg.setJMSDeliveryMode(DeliveryMode.NON_PERSISTENT);
+ }
+ }
+
+ if ((jmsHeaderPolicy != null) &&
+ (jmsHeaderPolicy.getJmsCorrelationId() != null)) {
+ jmsMsg.setJMSCorrelationID(jmsHeaderPolicy.getJmsCorrelationId());
+ } else if (jmsBinding.getOperationJMSCorrelationId(operationName) != null) {
+ jmsMsg.setJMSCorrelationID(jmsBinding.getOperationJMSCorrelationId(operationName));
+ }
+
+ if ((jmsHeaderPolicy != null) &&
+ (jmsHeaderPolicy.getJmsPriority() != null)) {
+ jmsMsg.setJMSPriority(jmsHeaderPolicy.getJmsPriority());
+ } else if (jmsBinding.getOperationJMSPriority(operationName) != null) {
+ jmsMsg.setJMSPriority(jmsBinding.getOperationJMSPriority(operationName));
+ }
+
+ if ((jmsHeaderPolicy != null) &&
+ (jmsHeaderPolicy.getJmsType() != null)) {
+ jmsMsg.setJMSType(jmsHeaderPolicy.getJmsType());
+ } else if (jmsBinding.getOperationJMSType(operationName) != null) {
+ jmsMsg.setJMSType(jmsBinding.getOperationJMSType(operationName));
+ }
+
+ ReferenceParameters parameters = tuscanyMsg.getFrom().getReferenceParameters();
+
+ Object conversationID = parameters.getConversationID();
+ if (conversationID != null) {
+ jmsMsg.setStringProperty(JMSBindingConstants.CONVERSATION_ID_PROPERTY, conversationID.toString());
+ }
+
+ if (hasCallback()) {
+
+ if (parameters.getCallbackID() != null) {
+ jmsMsg.setStringProperty(JMSBindingConstants.CALLBACK_ID_PROPERTY, parameters.getCallbackID().toString());
+ }
+
+ String callbackDestName = getCallbackDestinationName(reference);
+ if (callbackDestName != null) {
+ jmsMsg.setStringProperty(JMSBindingConstants.CALLBACK_Q_PROPERTY, callbackDestName);
+ }
+ }
+
+ if (jmsHeaderPolicy != null){
+ for (String propName : jmsHeaderPolicy.getProperties().keySet()) {
+ jmsMsg.setObjectProperty(propName, jmsHeaderPolicy.getProperties().get(propName));
+ }
+ }
+
+ for (String propName : jmsBinding.getPropertyNames()) {
+ Object value = jmsBinding.getProperty(propName);
+ jmsMsg.setObjectProperty(propName, value);
+ }
+
+ Map<String, Object> operationProperties = jmsBinding.getOperationProperties(operationName);
+ if (operationProperties != null) {
+ for (String propName : operationProperties.keySet()) {
+ Object value = operationProperties.get(propName);
+ jmsMsg.setObjectProperty(propName, value);
+ }
+ }
+
+ if (jmsTokenAuthenticationPolicy != null) {
+ Subject subject = SecurityUtil.getSubject(tuscanyMsg);
+ TokenPrincipal principal = SecurityUtil.getPrincipal(subject, TokenPrincipal.class);
+ if (principal != null){
+ jmsMsg.setStringProperty(jmsTokenAuthenticationPolicy.getTokenName().toString(), principal.getName());
+ }
+ }
+ }
+
+ protected boolean hasCallback() {
+ if (operation.getInterface() instanceof JavaInterface) {
+ JavaInterface jiface = (JavaInterface)operation.getInterface();
+ if (jiface.getCallbackClass() != null) {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ protected Message receiveReply(Session session, Destination replyToDest, String requestMsgId) throws JMSException, NamingException {
+ String msgSelector = "JMSCorrelationID = '" + requestMsgId + "'";
+ MessageConsumer consumer = session.createConsumer(replyToDest, msgSelector);
+
+ long receiveWait;
+ if ((jmsHeaderPolicy != null) &&
+ (jmsHeaderPolicy.getTimeToLive() != null)) {
+ receiveWait = jmsHeaderPolicy.getTimeToLive();
+ } else if (jmsBinding.getOperationJMSTimeToLive(operationName) != null) {
+ receiveWait = jmsBinding.getOperationJMSTimeToLive(operationName) * 2;
+ } else {
+ receiveWait = JMSBindingConstants.DEFAULT_TIME_TO_LIVE;
+ }
+
+ Message replyMsg;
+ try {
+ jmsResourceFactory.startConnection();
+ replyMsg = consumer.receive(receiveWait);
+ } finally {
+ consumer.close();
+ }
+ if (replyMsg == null) {
+ throw new JMSBindingException("No reply message received on " + replyToDest + " for message id " + requestMsgId);
+ }
+ return replyMsg;
+ }
+
+ protected String getCallbackDestinationName(RuntimeComponentReference reference) {
+ RuntimeComponentService s = (RuntimeComponentService)reference.getCallbackService();
+ JMSBinding b = s.getBinding(JMSBinding.class);
+ if (b != null) {
+ JMSBindingServiceBindingProvider bp = (JMSBindingServiceBindingProvider)s.getBindingProvider(b);
+ return bp.getDestinationName();
+ }
+ return null;
+ }
+
+ public boolean allowsPassByReference() {
+ // JMS always pass by value
+ return true;
+ }
+
+}
diff --git a/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/JMSBindingListener.java b/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/JMSBindingListener.java
new file mode 100644
index 0000000000..87b1bb21e2
--- /dev/null
+++ b/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/JMSBindingListener.java
@@ -0,0 +1,266 @@
+/*
+ * 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.lang.reflect.InvocationTargetException;
+import java.util.List;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageListener;
+import javax.jms.MessageProducer;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.Topic;
+import javax.naming.NamingException;
+import javax.security.auth.Subject;
+
+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.impl.JMSBindingException;
+import org.apache.tuscany.sca.binding.jms.policy.authentication.token.JMSTokenAuthenticationPolicy;
+import org.apache.tuscany.sca.core.assembly.EndpointReferenceImpl;
+import org.apache.tuscany.sca.core.invocation.MessageImpl;
+import org.apache.tuscany.sca.interfacedef.Operation;
+import org.apache.tuscany.sca.policy.PolicySet;
+import org.apache.tuscany.sca.policy.PolicySetAttachPoint;
+import org.apache.tuscany.sca.policy.SecurityUtil;
+import org.apache.tuscany.sca.policy.authentication.token.TokenPrincipal;
+import org.apache.tuscany.sca.runtime.EndpointReference;
+import org.apache.tuscany.sca.runtime.ReferenceParameters;
+import org.apache.tuscany.sca.runtime.RuntimeComponentService;
+
+/**
+ * Listener for the JMSBinding.
+ *
+ * @version $Rev$ $Date$
+ */
+public class JMSBindingListener implements MessageListener {
+
+ private static final Logger logger = Logger.getLogger(JMSBindingListener.class.getName());
+
+ private static final String ON_MESSAGE_METHOD_NAME = "onMessage";
+ private JMSBinding jmsBinding;
+ private Binding targetBinding;
+ private JMSResourceFactory jmsResourceFactory;
+ private RuntimeComponentService service;
+ private JMSMessageProcessor requestMessageProcessor;
+ private JMSMessageProcessor responseMessageProcessor;
+ private String correlationScheme;
+ private List<Operation> serviceOperations;
+ protected JMSTokenAuthenticationPolicy jmsTokenAuthenticationPolicy = null;
+
+ public JMSBindingListener(JMSBinding jmsBinding, JMSResourceFactory jmsResourceFactory, RuntimeComponentService service, Binding targetBinding) throws NamingException {
+ this.jmsBinding = jmsBinding;
+ this.jmsResourceFactory = jmsResourceFactory;
+ this.service = service;
+ this.targetBinding = targetBinding;
+ requestMessageProcessor = JMSMessageProcessorUtil.getRequestMessageProcessor(jmsBinding);
+ responseMessageProcessor = JMSMessageProcessorUtil.getResponseMessageProcessor(jmsBinding);
+ correlationScheme = jmsBinding.getCorrelationScheme();
+ serviceOperations = service.getInterfaceContract().getInterface().getOperations();
+
+ // find out which policies are active
+ if (jmsBinding instanceof PolicySetAttachPoint) {
+ List<PolicySet> policySets = ((PolicySetAttachPoint)jmsBinding).getApplicablePolicySets();
+ for (PolicySet ps : policySets) {
+ for (Object p : ps.getPolicies()) {
+ if (JMSTokenAuthenticationPolicy.class.isInstance(p)) {
+ jmsTokenAuthenticationPolicy = (JMSTokenAuthenticationPolicy)p;
+ }else {
+ // etc. check for other types of policy being present
+ }
+ }
+ }
+ }
+
+ }
+
+ public void onMessage(Message requestJMSMsg) {
+ logger.log(Level.FINE, "JMS service '" + service.getName() + "' received message " + requestJMSMsg);
+ try {
+ Object responsePayload = invokeService(requestJMSMsg);
+ sendReply(requestJMSMsg, responsePayload, false);
+ } catch (Throwable e) {
+ logger.log(Level.SEVERE, "Exception invoking service '" + service.getName(), e);
+ sendReply(requestJMSMsg, e, true);
+ }
+ }
+
+ /**
+ * Turn the JMS message back into a Tuscany message and invoke the target component
+ *
+ * @param requestJMSMsg
+ * @return
+ * @throws JMSException
+ * @throws InvocationTargetException
+ */
+ protected Object invokeService(Message requestJMSMsg) throws JMSException, InvocationTargetException {
+
+ String operationName = requestMessageProcessor.getOperationName(requestJMSMsg);
+ Operation operation = getTargetOperation(operationName);
+
+ MessageImpl tuscanyMsg = new MessageImpl();
+ tuscanyMsg.setOperation(operation);
+ if ("onMessage".equals(operation.getName())) {
+ tuscanyMsg.setBody(new Object[]{requestJMSMsg});
+ } else {
+ Object requestPayload = requestMessageProcessor.extractPayloadFromJMSMessage(requestJMSMsg);
+ tuscanyMsg.setBody(requestPayload);
+ }
+
+ setHeaderProperties(requestJMSMsg, tuscanyMsg, operation);
+
+ return service.getRuntimeWire(targetBinding).invoke(operation, tuscanyMsg);
+ }
+
+ protected Operation getTargetOperation(String operationName) {
+ Operation operation = null;
+
+ if (serviceOperations.size() == 1) {
+
+ // SCA JMS Binding Specification - Rule 1.5.1 line 203
+ operation = serviceOperations.get(0);
+
+ } else if (operationName != null) {
+
+ // SCA JMS Binding Specification - Rule 1.5.1 line 205
+ for (Operation op : serviceOperations) {
+ if (op.getName().equals(operationName)) {
+ operation = op;
+ break;
+ }
+ }
+
+ } else {
+
+ // SCA JMS Binding Specification - Rule 1.5.1 line 207
+ for (Operation op : serviceOperations) {
+ if (op.getName().equals(ON_MESSAGE_METHOD_NAME)) {
+ operation = op;
+ break;
+ }
+ }
+ }
+
+ if (operation == null) {
+ throw new JMSBindingException("Can't find operation " + (operationName != null ? operationName : ON_MESSAGE_METHOD_NAME));
+ }
+
+ return operation;
+ }
+
+ protected void setHeaderProperties(Message requestJMSMsg, MessageImpl tuscanyMsg, Operation operation) throws JMSException {
+
+ EndpointReference from = new EndpointReferenceImpl(null);
+ tuscanyMsg.setFrom(from);
+ from.setCallbackEndpoint(new EndpointReferenceImpl("/")); // TODO: whats this for?
+ ReferenceParameters parameters = from.getReferenceParameters();
+
+ String conversationID = requestJMSMsg.getStringProperty(JMSBindingConstants.CONVERSATION_ID_PROPERTY);
+ if (conversationID != null) {
+ parameters.setConversationID(conversationID);
+ }
+
+ if (service.getInterfaceContract().getCallbackInterface() != null) {
+
+ String callbackdestName = requestJMSMsg.getStringProperty(JMSBindingConstants.CALLBACK_Q_PROPERTY);
+ if (callbackdestName == null && operation.isNonBlocking()) {
+ // if the request has a replyTo but this service operation is oneway but the service uses callbacks
+ // then use the replyTo as the callback destination
+ Destination replyTo = requestJMSMsg.getJMSReplyTo();
+ if (replyTo != null) {
+ callbackdestName = (replyTo instanceof Queue) ? ((Queue)replyTo).getQueueName() : ((Topic)replyTo).getTopicName();
+ }
+ }
+
+ if (callbackdestName != null) {
+ // append "jms:" to make it an absolute uri so the invoker can determine it came in on the request
+ // as otherwise the invoker should use the uri from the service callback binding
+ parameters.setCallbackReference(new EndpointReferenceImpl("jms:" + callbackdestName));
+ }
+
+ String callbackID = requestJMSMsg.getStringProperty(JMSBindingConstants.CALLBACK_ID_PROPERTY);
+ if (callbackID != null) {
+ parameters.setCallbackID(callbackID);
+ }
+ }
+
+ if (jmsTokenAuthenticationPolicy != null) {
+ String token = requestJMSMsg.getStringProperty(jmsTokenAuthenticationPolicy.getTokenName().toString());
+
+ Subject subject = SecurityUtil.getSubject(tuscanyMsg);
+ TokenPrincipal principal = SecurityUtil.getPrincipal(subject, TokenPrincipal.class);
+
+ if (principal == null){
+ principal = new TokenPrincipal(token);
+ subject.getPrincipals().add(principal);
+ }
+
+ }
+ }
+
+ protected void sendReply(Message requestJMSMsg, Object responsePayload, boolean isFault) {
+ try {
+
+ if (requestJMSMsg.getJMSReplyTo() == null) {
+ // assume no reply is expected
+ if (responsePayload != null) {
+ logger.log(Level.FINE, "JMS service '" + service.getName() + "' dropped response as request has no replyTo");
+ }
+ return;
+ }
+
+ Session session = jmsResourceFactory.createSession();
+ Message replyJMSMsg;
+ if (isFault) {
+ replyJMSMsg = responseMessageProcessor.createFaultMessage(session, (Throwable)responsePayload);
+ } else {
+ replyJMSMsg = responseMessageProcessor.insertPayloadIntoJMSMessage(session, responsePayload);
+ }
+
+ replyJMSMsg.setJMSDeliveryMode(requestJMSMsg.getJMSDeliveryMode());
+ replyJMSMsg.setJMSPriority(requestJMSMsg.getJMSPriority());
+
+ if (correlationScheme == null || JMSBindingConstants.CORRELATE_MSG_ID.equalsIgnoreCase(correlationScheme)) {
+ replyJMSMsg.setJMSCorrelationID(requestJMSMsg.getJMSMessageID());
+ } else if (JMSBindingConstants.CORRELATE_CORRELATION_ID.equalsIgnoreCase(correlationScheme)) {
+ replyJMSMsg.setJMSCorrelationID(requestJMSMsg.getJMSCorrelationID());
+ }
+
+ Destination destination = requestJMSMsg.getJMSReplyTo();
+ MessageProducer producer = session.createProducer(destination);
+
+ producer.send(replyJMSMsg);
+
+ producer.close();
+ session.close();
+
+ } catch (JMSException e) {
+ throw new JMSBindingException(e);
+ } catch (NamingException e) {
+ throw new JMSBindingException(e);
+ }
+ }
+
+}
diff --git a/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/JMSBindingProviderFactory.java b/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/JMSBindingProviderFactory.java
new file mode 100644
index 0000000000..39e4cf0558
--- /dev/null
+++ b/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/JMSBindingProviderFactory.java
@@ -0,0 +1,68 @@
+/*
+ * 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 org.apache.tuscany.sca.binding.jms.impl.JMSBinding;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.core.UtilityExtensionPoint;
+import org.apache.tuscany.sca.provider.BindingProviderFactory;
+import org.apache.tuscany.sca.provider.ReferenceBindingProvider;
+import org.apache.tuscany.sca.provider.ServiceBindingProvider;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+import org.apache.tuscany.sca.runtime.RuntimeComponentReference;
+import org.apache.tuscany.sca.runtime.RuntimeComponentService;
+import org.apache.tuscany.sca.work.WorkScheduler;
+
+/**
+ * A factory from creating the JMS binding provider.
+ *
+ * @version $Rev$ $Date$
+ */
+public class JMSBindingProviderFactory implements BindingProviderFactory<JMSBinding> {
+
+ private WorkScheduler workScheduler;
+ private ExtensionPointRegistry extensionPoints;
+ private JMSResourceFactoryExtensionPoint jmsRFEP;
+
+ public JMSBindingProviderFactory(ExtensionPointRegistry extensionPoints) {
+ this.extensionPoints = extensionPoints;
+ UtilityExtensionPoint utilities = extensionPoints.getExtensionPoint(UtilityExtensionPoint.class);
+ workScheduler = utilities.getUtility(WorkScheduler.class);
+
+ jmsRFEP = (JMSResourceFactoryExtensionPoint)extensionPoints.getExtensionPoint(JMSResourceFactoryExtensionPoint.class);
+ if (jmsRFEP == null) {
+ jmsRFEP = new DefaultJMSResourceFactoryExtensionPoint();
+ }
+ }
+
+ public ReferenceBindingProvider createReferenceBindingProvider(RuntimeComponent component, RuntimeComponentReference reference, JMSBinding binding) {
+ JMSResourceFactory jmsRF = jmsRFEP.createJMSResourceFactory(binding);
+ return new JMSBindingReferenceBindingProvider(component, reference, binding, extensionPoints, jmsRF);
+ }
+
+ public ServiceBindingProvider createServiceBindingProvider(RuntimeComponent component, RuntimeComponentService service, JMSBinding binding) {
+ JMSResourceFactory jmsRF = jmsRFEP.createJMSResourceFactory(binding);
+ return new JMSBindingServiceBindingProvider(component, service, binding, binding, workScheduler, extensionPoints, jmsRF);
+ }
+
+ public Class<JMSBinding> getModelType() {
+ return JMSBinding.class;
+ }
+}
diff --git a/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/JMSBindingReferenceBindingProvider.java b/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/JMSBindingReferenceBindingProvider.java
new file mode 100644
index 0000000000..1bcc09e366
--- /dev/null
+++ b/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/JMSBindingReferenceBindingProvider.java
@@ -0,0 +1,134 @@
+/*
+ * 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.util.ArrayList;
+import java.util.List;
+
+import javax.jms.JMSException;
+
+import org.apache.axiom.om.OMElement;
+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.impl.JMSBindingException;
+import org.apache.tuscany.sca.binding.ws.WebServiceBinding;
+import org.apache.tuscany.sca.binding.ws.WebServiceBindingFactory;
+import org.apache.tuscany.sca.binding.ws.wsdlgen.BindingWSDLGenerator;
+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.Invoker;
+import org.apache.tuscany.sca.provider.ReferenceBindingProvider;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+import org.apache.tuscany.sca.runtime.RuntimeComponentReference;
+
+/**
+ * Implementation of the JMS reference binding provider.
+ *
+ * @version $Rev$ $Date$
+ */
+public class JMSBindingReferenceBindingProvider implements ReferenceBindingProvider {
+
+ private RuntimeComponentReference reference;
+ private JMSBinding jmsBinding;
+ private List<JMSBindingInvoker> jmsBindingInvokers = new ArrayList<JMSBindingInvoker>();
+ private JMSResourceFactory jmsResourceFactory;
+ private RuntimeComponent component;
+ private InterfaceContract wsdlInterfaceContract;
+ private ExtensionPointRegistry extensions;
+
+ public JMSBindingReferenceBindingProvider(RuntimeComponent component, RuntimeComponentReference reference, JMSBinding binding, ExtensionPointRegistry extensions, JMSResourceFactory jmsResourceFactory) {
+ this.reference = reference;
+ this.jmsBinding = binding;
+ this.extensions = extensions;
+ this.component = component;
+ this.jmsResourceFactory = jmsResourceFactory;
+
+ if (XMLTextMessageProcessor.class.isAssignableFrom(JMSMessageProcessorUtil.getRequestMessageProcessor(jmsBinding).getClass())) {
+ setXMLDataBinding(reference);
+ }
+
+ }
+
+ protected void setXMLDataBinding(RuntimeComponentReference reference) {
+
+ WebServiceBindingFactory wsFactory = extensions.getExtensionPoint(WebServiceBindingFactory.class);
+ WebServiceBinding wsBinding = wsFactory.createWebServiceBinding();
+ BindingWSDLGenerator.generateWSDL(component, reference, wsBinding, extensions, null);
+ wsdlInterfaceContract = wsBinding.getBindingInterfaceContract();
+ wsdlInterfaceContract.getInterface().resetDataBinding(OMElement.class.getName());
+
+ // TODO: TUSCANY-xxx, section 5.2 "Default Data Binding" in the JMS binding spec
+
+// try {
+// InterfaceContract ic = (InterfaceContract)reference.getInterfaceContract().clone();
+//
+// Interface ii = (Interface)ic.getInterface().clone();
+// ii.resetDataBinding("org.apache.axiom.om.OMElement");
+// ic.setInterface(ii);
+// reference.setInterfaceContract(ic);
+//
+// } catch (CloneNotSupportedException e) {
+// throw new RuntimeException(e);
+// }
+ }
+
+ public Invoker createInvoker(Operation operation) {
+
+ if (jmsBinding.getDestinationName().equals(JMSBindingConstants.DEFAULT_DESTINATION_NAME)) {
+ if (!reference.isCallback()) {
+ throw new JMSBindingException("No destination specified for reference " + reference.getName());
+ }
+ }
+
+ JMSBindingInvoker invoker = new JMSBindingInvoker(jmsBinding, operation, jmsResourceFactory, reference);
+ jmsBindingInvokers.add(invoker);
+ return invoker;
+ }
+
+ public boolean supportsOneWayInvocation() {
+ return true;
+ }
+
+ public InterfaceContract getBindingInterfaceContract() {
+ if (wsdlInterfaceContract != null) {
+ return wsdlInterfaceContract;
+ } else {
+ if (reference.getInterfaceContract() == null) {
+ return reference.getReference().getInterfaceContract();
+ } else {
+ return reference.getInterfaceContract();
+ }
+ }
+ }
+
+ public void start() {
+
+ }
+
+ public void stop() {
+ try {
+ jmsResourceFactory.closeConnection();
+ } catch (JMSException e) {
+ throw new JMSBindingException(e);
+ }
+ }
+
+}
diff --git a/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/JMSBindingServiceBindingProvider.java b/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/JMSBindingServiceBindingProvider.java
new file mode 100644
index 0000000000..fc9cacf5e1
--- /dev/null
+++ b/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/JMSBindingServiceBindingProvider.java
@@ -0,0 +1,306 @@
+/*
+ * 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.util.logging.Level;
+import java.util.logging.Logger;
+
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.MessageConsumer;
+import javax.jms.Queue;
+import javax.jms.Session;
+import javax.jms.Topic;
+import javax.naming.NamingException;
+
+import org.apache.axiom.om.OMElement;
+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.impl.JMSBindingException;
+import org.apache.tuscany.sca.binding.ws.WebServiceBinding;
+import org.apache.tuscany.sca.binding.ws.WebServiceBindingFactory;
+import org.apache.tuscany.sca.binding.ws.wsdlgen.BindingWSDLGenerator;
+import org.apache.tuscany.sca.core.ExtensionPointRegistry;
+import org.apache.tuscany.sca.interfacedef.InterfaceContract;
+import org.apache.tuscany.sca.provider.ServiceBindingProvider;
+import org.apache.tuscany.sca.runtime.RuntimeComponent;
+import org.apache.tuscany.sca.runtime.RuntimeComponentService;
+import org.apache.tuscany.sca.work.WorkScheduler;
+
+/**
+ * Implementation of the JMS service binding provider.
+ *
+ * @version $Rev$ $Date$
+ */
+public class JMSBindingServiceBindingProvider implements ServiceBindingProvider {
+ private static final Logger logger = Logger.getLogger(JMSBindingServiceBindingProvider.class.getName());
+
+ private RuntimeComponentService service;
+ private Binding targetBinding;
+ private JMSBinding jmsBinding;
+ private JMSResourceFactory jmsResourceFactory;
+ private MessageConsumer consumer;
+ private WorkScheduler workScheduler;
+ private boolean running;
+
+ private Destination destination;
+
+ private ExtensionPointRegistry extensionPoints;
+
+ private RuntimeComponent component;
+ private InterfaceContract wsdlInterfaceContract;
+
+ public JMSBindingServiceBindingProvider(RuntimeComponent component, RuntimeComponentService service, Binding targetBinding, JMSBinding binding, WorkScheduler workScheduler, ExtensionPointRegistry extensionPoints, JMSResourceFactory jmsResourceFactory) {
+ this.component = component;
+ this.service = service;
+ this.jmsBinding = binding;
+ this.workScheduler = workScheduler;
+ this.targetBinding = targetBinding;
+ this.extensionPoints = extensionPoints;
+ this.jmsResourceFactory = jmsResourceFactory;
+
+ if (jmsBinding.getDestinationName().equals(JMSBindingConstants.DEFAULT_DESTINATION_NAME)) {
+ if (!service.isCallback()) {
+ // use the SCA service name as the default destination name
+ jmsBinding.setDestinationName(service.getName());
+ }
+ }
+
+ if (XMLTextMessageProcessor.class.isAssignableFrom(JMSMessageProcessorUtil.getRequestMessageProcessor(jmsBinding).getClass())) {
+ if (!isOnMessage()) {
+ setXMLDataBinding(service);
+ }
+ }
+
+ }
+
+ protected boolean isOnMessage() {
+ InterfaceContract ic = getBindingInterfaceContract();
+ if (ic.getInterface().getOperations().size() != 1) {
+ return false;
+ }
+ return "onMessage".equals(ic.getInterface().getOperations().get(0).getName());
+ }
+
+ protected void setXMLDataBinding(RuntimeComponentService service) {
+ if (service.getInterfaceContract() != null) {
+ WebServiceBindingFactory wsFactory = extensionPoints.getExtensionPoint(WebServiceBindingFactory.class);
+ WebServiceBinding wsBinding = wsFactory.createWebServiceBinding();
+ BindingWSDLGenerator.generateWSDL(component, service, wsBinding, extensionPoints, null);
+ wsdlInterfaceContract = wsBinding.getBindingInterfaceContract();
+ wsdlInterfaceContract.getInterface().resetDataBinding(OMElement.class.getName());
+
+ // TODO: TUSCANY-xxx, section 5.2 "Default Data Binding" in the JMS binding spec
+
+// try {
+// InterfaceContract ic = (InterfaceContract)service.getInterfaceContract().clone();
+// Interface ii = ic.getInterface();
+// if (ii.getOperations().size() == 1 && "onMessage".equals(ii.getOperations().get(0).getName())) {
+// return;
+// }
+// ii = (Interface)ii.clone();
+// ii.resetDataBinding("org.apache.axiom.om.OMElement");
+// ic.setInterface(ii);
+// service.setInterfaceContract(ic);
+//
+// } catch (CloneNotSupportedException e) {
+// throw new RuntimeException(e);
+// }
+ }
+ }
+
+ public InterfaceContract getBindingInterfaceContract() {
+ if (wsdlInterfaceContract != null) {
+ return wsdlInterfaceContract;
+ } else {
+ return service.getInterfaceContract();
+ }
+ }
+
+ public boolean supportsOneWayInvocation() {
+ return true;
+ }
+
+ public void start() {
+ this.running = true;
+
+ try {
+ registerListerner();
+ } catch (Exception e) {
+ throw new JMSBindingException("Error starting JMSServiceBinding", e);
+ }
+ }
+
+ public void stop() {
+ this.running = false;
+ try {
+ consumer.close();
+ jmsResourceFactory.closeConnection();
+ } catch (Exception e) {
+ // if using an embedded broker then when shutting down Tuscany the broker may get closed
+ // before this stop method is called. I can't see how to detect that so for now just
+ // ignore the exception if the message is that the transport is already disposed
+ if (!"Transport disposed.".equals(e.getMessage())) {
+ throw new JMSBindingException("Error stopping JMSServiceBinding", e);
+ }
+ }
+ }
+
+ private void registerListerner() throws NamingException, JMSException {
+
+ Session session = jmsResourceFactory.createSession();
+ destination = lookupDestinationQueue();
+ if (destination == null) {
+ destination = session.createTemporaryQueue();
+ }
+
+ if (jmsBinding.getJMSSelector() != null) {
+ consumer = session.createConsumer(destination, jmsBinding.getJMSSelector());
+ } else {
+ consumer = session.createConsumer(destination);
+ }
+
+ final JMSBindingListener listener = new JMSBindingListener(jmsBinding, jmsResourceFactory, service, targetBinding);
+ try {
+
+ consumer.setMessageListener(listener);
+ jmsResourceFactory.startConnection();
+
+ } catch (javax.jms.IllegalStateException e) {
+
+ // setMessageListener not allowed in JEE container so use Tuscany threads
+
+ jmsResourceFactory.startConnection();
+ workScheduler.scheduleWork(new Runnable() {
+ public void run() {
+ try {
+ while (running) {
+ final Message msg = consumer.receive();
+ workScheduler.scheduleWork(new Runnable() {
+ public void run() {
+ try {
+ listener.onMessage(msg);
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ }
+ } catch (Exception e) {
+ e.printStackTrace();
+ }
+ }
+ });
+ }
+ logger.log(Level.INFO, "JMS " + (service.isCallback() ? "callback service" : "service")
+ + " '"
+ + service.getName()
+ + "' listening on destination "
+ + ((destination instanceof Queue) ? ((Queue)destination).getQueueName() : ((Topic)destination).getTopicName()));
+ }
+
+ /**
+ * Looks up the Destination Queue for the JMS Binding.
+ * <p>
+ * What happens in the look up will depend on the create mode specified for the JMS Binding:
+ * <ul>
+ * <li>always - the JMS queue is always created. It is an error if the queue already exists
+ * <li>ifnotexist - the JMS queue is created if it does not exist. It is not an error if the queue already exists
+ * <li>never - the JMS queue is never created. It is an error if the queue does not exist
+ * </ul>
+ * See the SCA JMS Binding specification for more information.
+ * <p>
+ *
+ * @return The Destination queue.
+ * @throws NamingException Failed to lookup JMS queue
+ * @throws JMSBindingException Failed to lookup JMS Queue. Probable cause is that the JMS queue's current existence/non-existence is not
+ * compatible with the create mode specified on the binding
+ */
+ private Destination lookupDestinationQueue() throws NamingException, JMSBindingException {
+
+ if (service.isCallback() && JMSBindingConstants.DEFAULT_DESTINATION_NAME.equals(jmsBinding.getDestinationName())) {
+ // if its a callback service returning null indicates to use a temporary queue
+ return null;
+ }
+
+ Destination destination = jmsResourceFactory.lookupDestination(jmsBinding.getDestinationName());
+
+ String qCreateMode = jmsBinding.getDestinationCreate();
+ if (qCreateMode.equals(JMSBindingConstants.CREATE_ALWAYS)) {
+ // In this mode, the queue must not already exist as we are creating it
+ if (destination != null) {
+ throw new JMSBindingException("JMS Destination " + jmsBinding.getDestinationName()
+ + " already exists but has create mode of \""
+ + qCreateMode
+ + "\" while registering service "
+ + service.getName()
+ + " listener");
+ }
+
+ // Create the queue
+ destination = jmsResourceFactory.createDestination(jmsBinding.getDestinationName());
+
+ } else if (qCreateMode.equals(JMSBindingConstants.CREATE_IF_NOT_EXIST)) {
+ // In this mode, the queue may nor may not exist. It will be created if it does not exist
+ if (destination == null) {
+ destination = jmsResourceFactory.createDestination(jmsBinding.getDestinationName());
+ }
+
+ } else if (qCreateMode.equals(JMSBindingConstants.CREATE_NEVER)) {
+ // In this mode, the queue must have already been created.
+ if (destination == null) {
+ throw new JMSBindingException("JMS Destination " + jmsBinding.getDestinationName()
+ + " not found but create mode of \""
+ + qCreateMode
+ + "\" while registering service "
+ + service.getName()
+ + " listener");
+ }
+ }
+
+ // Make sure we ended up with a queue
+ if (destination == null) {
+ throw new JMSBindingException("JMS Destination " + jmsBinding.getDestinationName()
+ + " not found with create mode of \""
+ + qCreateMode
+ + "\" while registering service "
+ + service.getName()
+ + " listener");
+ }
+
+ return destination;
+ }
+
+ public String getDestinationName() {
+ try {
+ if (destination instanceof Queue) {
+ return ((Queue)destination).getQueueName();
+ } else if (destination instanceof Topic) {
+ return ((Topic)destination).getTopicName();
+ } else {
+ return null;
+ }
+ } catch (JMSException e) {
+ throw new JMSBindingException(e);
+ }
+ }
+}
diff --git a/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/JMSMessageProcessor.java b/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/JMSMessageProcessor.java
new file mode 100644
index 0000000000..821b9d7873
--- /dev/null
+++ b/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/JMSMessageProcessor.java
@@ -0,0 +1,55 @@
+/*
+ * 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 javax.jms.Message;
+import javax.jms.Session;
+
+/**
+ * Interface for a component that does operation selection and message payload processing
+ *
+ * @version $Rev$ $Date$
+ */
+public interface JMSMessageProcessor {
+
+ /**
+ * Get the operation name from a JMS Message
+ */
+ String getOperationName(Message message);
+
+ /**
+ * Set the operation name on a JMS Message
+ */
+ void setOperationName(String operationName, Message message);
+
+ /**
+ * Extracts the payload from a JMS Message
+ */
+ Object extractPayloadFromJMSMessage(Message msg);
+
+ /**
+ * Create a JMS Message containing the payload
+ */
+ Message insertPayloadIntoJMSMessage(Session session, Object payload);
+
+ /**
+ * Create a JMS Message for reporting an exception
+ */
+ Message createFaultMessage(Session session, Throwable responsePayload);
+}
diff --git a/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/JMSMessageProcessorUtil.java b/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/JMSMessageProcessorUtil.java
new file mode 100644
index 0000000000..699b1cb176
--- /dev/null
+++ b/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/JMSMessageProcessorUtil.java
@@ -0,0 +1,75 @@
+/*
+ * 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.lang.reflect.Constructor;
+
+import org.apache.tuscany.sca.binding.jms.impl.JMSBinding;
+import org.apache.tuscany.sca.binding.jms.impl.JMSBindingException;
+
+/**
+ * Utility methods to load JMS message processors.
+ *
+ * @version $Rev: $ $Date: $
+ */
+public class JMSMessageProcessorUtil {
+
+ /**
+ * Used to create instances of the JMSResourceFactory and RequestMessageProcessor and ResponseMessageProcessor from
+ * string based class name provided in the configuration
+ *
+ * @param cl ClassLoader
+ * @param className the string based class name to load and instantiate
+ * @return the new object
+ */
+ private static Object instantiate(ClassLoader cl, String className, JMSBinding binding) {
+ Object instance;
+ if (cl == null) {
+ cl = binding.getClass().getClassLoader();
+ }
+
+ try {
+ Class<?> clazz;
+
+ try {
+ clazz = cl.loadClass(className);
+ } catch (ClassNotFoundException e) {
+ clazz = binding.getClass().getClassLoader().loadClass(className);
+ }
+
+ Constructor<?> constructor = clazz.getDeclaredConstructor(new Class[] {JMSBinding.class});
+ instance = constructor.newInstance(binding);
+
+ } catch (Throwable e) {
+ throw new JMSBindingException("Exception instantiating OperationAndDataBinding class", e);
+ }
+
+ return instance;
+ }
+
+ public static JMSMessageProcessor getRequestMessageProcessor(JMSBinding binding) {
+ return (JMSMessageProcessor)instantiate(null, binding.getRequestMessageProcessorName(), binding);
+ }
+
+ public static JMSMessageProcessor getResponseMessageProcessor(JMSBinding binding) {
+ return (JMSMessageProcessor)instantiate(null, binding.getResponseMessageProcessorName(), binding);
+ }
+
+}
diff --git a/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/JMSResourceFactory.java b/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/JMSResourceFactory.java
new file mode 100644
index 0000000000..773be84c7f
--- /dev/null
+++ b/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/JMSResourceFactory.java
@@ -0,0 +1,67 @@
+/*
+ * 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 javax.jms.Connection;
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.Session;
+import javax.naming.NamingException;
+
+public interface JMSResourceFactory {
+
+ /*
+ * This is a simple implementation where a connection is created per binding Ideally the resource factory should be
+ * able to leverage the host environment to provide connection pooling if it can. E.g. if Tuscany is running inside
+ * an AppServer Then we could leverage the JMS resources it provides
+ *
+ * @see org.apache.tuscany.binding.jms.JMSResourceFactory#getConnection()
+ */
+ public abstract Connection getConnection() throws NamingException, JMSException;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.tuscany.binding.jms.JMSResourceFactory#createSession()
+ */
+ public abstract Session createSession() throws JMSException, NamingException;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.tuscany.binding.jms.JMSResourceFactory#startConnection()
+ */
+ public abstract void startConnection() throws JMSException, NamingException;
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.tuscany.binding.jms.JMSResourceFactory#closeConnection()
+ */
+ public abstract void closeConnection() throws JMSException;
+
+ public abstract Destination lookupDestination(String destName) throws NamingException;
+
+ /**
+ * You can create a destination in ActiveMQ (and have it appear in JNDI) by putting "dynamicQueues/" in front of the queue name being looked up
+ */
+ public abstract Destination createDestination(String jndiName) throws NamingException;
+
+}
diff --git a/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/JMSResourceFactoryExtensionPoint.java b/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/JMSResourceFactoryExtensionPoint.java
new file mode 100644
index 0000000000..57fbfb3215
--- /dev/null
+++ b/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/JMSResourceFactoryExtensionPoint.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.binding.jms.provider;
+
+import org.apache.tuscany.sca.binding.jms.impl.JMSBinding;
+
+public interface JMSResourceFactoryExtensionPoint {
+
+ JMSResourceFactory createJMSResourceFactory(JMSBinding binding);
+
+}
diff --git a/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/JMSResourceFactoryImpl.java b/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/JMSResourceFactoryImpl.java
new file mode 100644
index 0000000000..6efcb2010f
--- /dev/null
+++ b/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/JMSResourceFactoryImpl.java
@@ -0,0 +1,223 @@
+/*
+ * 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.util.Properties;
+
+import javax.jms.Connection;
+import javax.jms.ConnectionFactory;
+import javax.jms.Destination;
+import javax.jms.JMSException;
+import javax.jms.Session;
+import javax.naming.Context;
+import javax.naming.InitialContext;
+import javax.naming.NamingException;
+
+import org.apache.tuscany.sca.binding.jms.impl.JMSBindingConstants;
+import org.apache.tuscany.sca.binding.jms.impl.JMSBindingException;
+
+/**
+ * Abstracts away any JMS provide specific feature from the JMS binding
+ *
+ * @version $Rev$ $Date$
+ */
+public class JMSResourceFactoryImpl implements JMSResourceFactory {
+
+ private String initialContextFactoryName;
+ private String connectionFactoryName = "ConnectionFactory";
+ private String jndiURL;
+
+ private Connection connection;
+ private Context context;
+ private boolean isConnectionStarted;
+
+ public JMSResourceFactoryImpl(String connectionFactoryName, String initialContextFactoryName, String jndiURL) {
+ if (connectionFactoryName != null && connectionFactoryName.trim().length() > 0) {
+ this.connectionFactoryName = connectionFactoryName.trim();
+ }
+ if (initialContextFactoryName != null && initialContextFactoryName.trim().length() > 0) {
+ this.initialContextFactoryName = initialContextFactoryName.trim();
+ }
+ if (jndiURL != null) {
+ this.jndiURL = jndiURL.trim();
+ }
+ }
+
+ /*
+ * This is a simple implementation where a connection is created per binding Ideally the resource factory should be
+ * able to leverage the host environment to provide connection pooling if it can. E.g. if Tuscany is running inside
+ * an AppServer Then we could leverage the JMS resources it provides
+ *
+ * @see org.apache.tuscany.sca.binding.jms.provider.JMSResourceFactory#getConnection()
+ */
+ public Connection getConnection() throws NamingException, JMSException {
+ if (connection == null) {
+ createConnection();
+ }
+ return connection;
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.tuscany.sca.binding.jms.provider.JMSResourceFactory#createSession()
+ */
+ public Session createSession() throws JMSException, NamingException {
+ return getConnection().createSession(false, Session.AUTO_ACKNOWLEDGE);
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.tuscany.sca.binding.jms.provider.JMSResourceFactory#startConnection()
+ */
+ public void startConnection() throws JMSException, NamingException {
+ if (!isConnectionStarted) {
+ getConnection().start();
+ isConnectionStarted = true;
+ }
+ }
+
+ /*
+ * (non-Javadoc)
+ *
+ * @see org.apache.tuscany.sca.binding.jms.provider.JMSResourceFactory#closeConnection()
+ */
+ public void closeConnection() throws JMSException {
+ if (connection != null) {
+ try {
+ connection.close();
+ } catch (JMSException e) {
+ // if using an embedded broker then when shutting down Tuscany the broker may get closed
+ // before this stop method is called. I can't see how to detect that so for now just
+ // ignore the exception if the message is that the transport is already disposed
+ if (!e.getMessage().contains("disposed")) {
+ throw e;
+ }
+ }
+ }
+ }
+
+ private void createConnection() throws NamingException, JMSException {
+ ConnectionFactory connectionFactory = (ConnectionFactory)jndiLookUp(connectionFactoryName);
+ if (connectionFactory == null) {
+ throw new JMSBindingException("connection factory not found: " + connectionFactoryName);
+ }
+ connection = connectionFactory.createConnection();
+ }
+
+ private synchronized Context getInitialContext() throws NamingException {
+ if (context == null) {
+ Properties props = new Properties();
+
+ if (initialContextFactoryName != null) {
+ props.setProperty(Context.INITIAL_CONTEXT_FACTORY, initialContextFactoryName);
+ }
+ if (jndiURL != null) {
+ props.setProperty(Context.PROVIDER_URL, jndiURL);
+ }
+
+ initJREEnvironment(props);
+
+ context = new InitialContext(props);
+ }
+ return context;
+ }
+
+ /**
+ * If using the WAS JMS Client with a non-IBM JRE then an additional
+ * environment property needs to be set to initialize the ORB correctly.
+ * See: http://www-1.ibm.com/support/docview.wss?uid=swg24012804
+ */
+ private void initJREEnvironment(Properties props) {
+ if ("com.ibm.websphere.naming.WsnInitialContextFactory".equals(props.get(Context.INITIAL_CONTEXT_FACTORY))) {
+ String vendor = System.getProperty("java.vendor");
+ if (vendor == null || !vendor.contains("IBM")) {
+ props.setProperty("com.ibm.CORBA.ORBInit", "com.ibm.ws.sib.client.ORB");
+ }
+ }
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.tuscany.sca.binding.jms.provider.JMSResourceFactory#lookupDestination(java.lang.String)
+ */
+ public Destination lookupDestination(String destName) throws NamingException {
+ if (JMSBindingConstants.DEFAULT_DESTINATION_NAME.equals(destName)) {
+ return null;
+ }
+
+ Destination dest = (Destination)jndiLookUp(destName);
+ if (dest == null) {
+ dest = lookupPhysical(destName);
+ }
+ return dest;
+ }
+
+ protected Destination lookupPhysical(String jndiName) {
+
+ // TODO: the SCA JMS spec says a destination name may be a non-jndi plain destination name
+
+// Session session = null;
+// try {
+//
+// Destination dest;
+// session = createSession();
+// dest = session.createQueue(jndiName);
+// return dest;
+//
+// } catch (JMSException e) {
+// throw new JMSBindingException(e);
+// } catch (NamingException e) {
+// throw new JMSBindingException(e);
+// } finally {
+// if (session != null) {
+// try {
+// session.close();
+// } catch (JMSException e) {
+// throw new JMSBindingException(e);
+// }
+// }
+// }
+ return null;
+ }
+
+ /* (non-Javadoc)
+ * @see org.apache.tuscany.sca.binding.jms.provider.JMSResourceFactory#createDestination(java.lang.String)
+ */
+ public Destination createDestination(String jndiName) throws NamingException {
+ return lookupDestination("dynamicQueues/" + jndiName);
+ }
+
+ protected Object jndiLookUp(String name) {
+ Object o = null;
+ try {
+ o = getInitialContext().lookup("java:comp/env/" + name);
+ } catch (NamingException ex) {
+ // ignore
+ }
+ if (o == null) {
+ try {
+ o = getInitialContext().lookup(name);
+ } catch (NamingException ex) {
+ // ignore
+ }
+ }
+ return o;
+ }
+}
diff --git a/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/ObjectMessageProcessor.java b/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/ObjectMessageProcessor.java
new file mode 100644
index 0000000000..e9ae3cecaa
--- /dev/null
+++ b/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/ObjectMessageProcessor.java
@@ -0,0 +1,75 @@
+/*
+ * 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 javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.ObjectMessage;
+import javax.jms.Session;
+
+import org.apache.tuscany.sca.binding.jms.impl.JMSBinding;
+import org.apache.tuscany.sca.binding.jms.impl.JMSBindingException;
+
+/**
+ * MessageProcessor for sending/receiving Serializable objects with the JMSBinding.
+ *
+ * @version $Rev$ $Date$
+ */
+public class ObjectMessageProcessor extends AbstractMessageProcessor {
+
+ public ObjectMessageProcessor(JMSBinding jmsBinding) {
+ super(jmsBinding);
+ }
+
+ @Override
+ protected Object[] extractPayload(Message msg) {
+ try {
+
+ Object o = ((ObjectMessage)msg).getObject();
+ if (o != null && o.getClass().isArray()) {
+ return (Object[])o;
+ } else {
+ return new Object[] { o};
+ }
+
+ } catch (JMSException e) {
+ throw new JMSBindingException(e);
+ }
+ }
+
+ @Override
+ protected Message createJMSMessage(Session session, Object o) {
+ try {
+
+ if (!(o instanceof Serializable)) {
+ throw new IllegalStateException("JMS ObjectMessage payload not Serializable: " + o);
+ }
+
+ ObjectMessage message = session.createObjectMessage();
+ message.setObject((Serializable)o);
+ return message;
+
+ } catch (JMSException e) {
+ throw new JMSBindingException(e);
+ }
+ }
+
+}
diff --git a/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/TextMessageProcessor.java b/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/TextMessageProcessor.java
new file mode 100644
index 0000000000..d8490c6223
--- /dev/null
+++ b/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/TextMessageProcessor.java
@@ -0,0 +1,68 @@
+/*
+ * 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 javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+
+import org.apache.tuscany.sca.binding.jms.impl.JMSBinding;
+import org.apache.tuscany.sca.binding.jms.impl.JMSBindingException;
+
+/**
+ * MessageProcessor for sending/receiving javax.jms.TextMessage with the JMSBinding.
+ *
+ * @version $Rev$ $Date$
+ */
+public class TextMessageProcessor extends AbstractMessageProcessor {
+
+ public TextMessageProcessor(JMSBinding jmsBinding) {
+ super(jmsBinding);
+ }
+
+ @Override
+ protected Object[] extractPayload(Message msg) {
+ try {
+
+ if (!(msg instanceof TextMessage)) {
+ throw new IllegalStateException("expecting JMS TextMessage: " + msg);
+ }
+
+ return new Object[] {((TextMessage)msg).getText()};
+
+ } catch (JMSException e) {
+ throw new JMSBindingException(e);
+ }
+ }
+
+ @Override
+ protected Message createJMSMessage(Session session, Object o) {
+ try {
+
+ TextMessage message = session.createTextMessage();
+ message.setText(String.valueOf(o));
+ return message;
+
+ } catch (JMSException e) {
+ throw new JMSBindingException(e);
+ }
+ }
+
+}
diff --git a/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/XMLTextMessageProcessor.java b/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/XMLTextMessageProcessor.java
new file mode 100644
index 0000000000..88dd41cc57
--- /dev/null
+++ b/sandbox/event/modules/binding-jms-runtime/src/main/java/org/apache/tuscany/sca/binding/jms/provider/XMLTextMessageProcessor.java
@@ -0,0 +1,90 @@
+/*
+ * 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.StringReader;
+
+import javax.jms.JMSException;
+import javax.jms.Message;
+import javax.jms.Session;
+import javax.jms.TextMessage;
+import javax.xml.stream.XMLInputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamReader;
+
+import org.apache.axiom.om.OMElement;
+import org.apache.axiom.om.impl.builder.StAXOMBuilder;
+import org.apache.tuscany.sca.binding.jms.impl.JMSBinding;
+import org.apache.tuscany.sca.binding.jms.impl.JMSBindingException;
+
+/**
+ * MessageProcessor for sending/receiving XML javax.jms.TextMessage with the JMSBinding.
+ *
+ * @version $Rev$ $Date$
+ */
+public class XMLTextMessageProcessor extends AbstractMessageProcessor {
+
+ public XMLTextMessageProcessor(JMSBinding jmsBinding) {
+ super(jmsBinding);
+ }
+
+ @Override
+ protected Object[] extractPayload(Message msg) {
+ try {
+
+ String xml = ((TextMessage)msg).getText();
+ Object[] os;
+ if (xml != null) {
+ XMLStreamReader reader = XMLInputFactory.newInstance().createXMLStreamReader(new StringReader(xml));
+ StAXOMBuilder builder = new StAXOMBuilder(reader);
+ os = new Object[] {builder.getDocumentElement()};
+ } else {
+ os = new Object[] {};
+ }
+ return os;
+
+ } catch (XMLStreamException e) {
+ throw new JMSBindingException(e);
+ } catch (JMSException e) {
+ throw new JMSBindingException(e);
+ }
+ }
+
+ @Override
+ protected Message createJMSMessage(Session session, Object o) {
+ try {
+
+ TextMessage message = session.createTextMessage();
+
+ if (o instanceof OMElement) {
+ message.setText(o.toString());
+ } else if ((o instanceof Object[]) && ((Object[])o)[0] instanceof OMElement) {
+ message.setText(((Object[])o)[0].toString());
+ } else if (o != null) {
+ throw new IllegalStateException("expecting OMElement payload: " + o);
+ }
+
+ return message;
+
+ } catch (JMSException e) {
+ throw new JMSBindingException(e);
+ }
+ }
+
+}