/* * Copyright (c) 2005-2014, WSO2 Inc. (http://www.wso2.org) All Rights Reserved. * * WSO2 Inc. 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.wso2.carbon.inbound.endpoint.protocol.jms.factory; import java.util.Properties; import javax.jms.Connection; import javax.jms.ConnectionFactory; import javax.jms.Destination; import javax.jms.JMSException; import javax.jms.MessageConsumer; import javax.jms.MessageProducer; import javax.jms.Queue; import javax.jms.QueueConnection; import javax.jms.QueueConnectionFactory; import javax.jms.QueueSession; import javax.jms.Session; import javax.jms.Topic; import javax.jms.TopicConnection; import javax.jms.TopicConnectionFactory; import javax.jms.TopicSession; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NameNotFoundException; import javax.naming.NamingException; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.wso2.carbon.inbound.endpoint.protocol.jms.JMSConstants; import org.wso2.carbon.inbound.endpoint.protocol.jms.JMSUtils; /** * use of factory server down and up jms spec transport.jms.MessageSelector * isDurable * * */ public class JMSConnectionFactory implements ConnectionFactory, QueueConnectionFactory, TopicConnectionFactory { private static final Log logger = LogFactory.getLog(JMSConnectionFactory.class.getName()); protected Context ctx; protected ConnectionFactory connectionFactory; protected String connectionFactoryString; protected JMSConstants.JMSDestinationType destinationType; private Destination destination; protected String destinationName; protected boolean transactedSession = false; protected int sessionAckMode = 0; protected String jmsSpec; protected boolean isDurable; protected boolean noPubSubLocal; protected String clientId; protected String subscriptionName; protected String messageSelector; protected boolean isSharedSubscription; public JMSConnectionFactory(Properties properties) { try { ctx = new InitialContext(properties); } catch (NamingException e) { logger.error("NamingException while obtaining initial context. " + e.getMessage(), e); } String connectionFactoryType = properties.getProperty(JMSConstants.CONNECTION_FACTORY_TYPE); if ("topic".equals(connectionFactoryType)) { this.destinationType = JMSConstants.JMSDestinationType.TOPIC; } else { this.destinationType = JMSConstants.JMSDestinationType.QUEUE; } if(properties.getProperty(JMSConstants.PARAM_JMS_SPEC_VER) == null || JMSConstants.JMS_SPEC_VERSION_1_1.equals(properties.getProperty(JMSConstants.PARAM_JMS_SPEC_VER))){ jmsSpec = JMSConstants.JMS_SPEC_VERSION_1_1; }else if(JMSConstants.JMS_SPEC_VERSION_2_0.equals( properties.getProperty(JMSConstants.PARAM_JMS_SPEC_VER))){ jmsSpec = JMSConstants.JMS_SPEC_VERSION_2_0; }else{ jmsSpec = JMSConstants.JMS_SPEC_VERSION_1_0; } if( "true".equalsIgnoreCase(properties.getProperty(JMSConstants.PARAM_IS_SHARED_SUBSCRIPTION))){ isSharedSubscription = true; } else{ isSharedSubscription = false; } noPubSubLocal = Boolean.valueOf(properties.getProperty(JMSConstants.PARAM_PUBSUB_NO_LOCAL)); clientId = properties.getProperty(JMSConstants.PARAM_DURABLE_SUB_CLIENT_ID); subscriptionName = properties.getProperty(JMSConstants.PARAM_DURABLE_SUB_NAME); if (isSharedSubscription) { if ( subscriptionName == null ){ logger.info( "Subscription name is not given. Therefor declaring a non-shared subscription" ); isSharedSubscription = false; } } String subDurable = properties.getProperty(JMSConstants.PARAM_SUB_DURABLE); if (subDurable != null) { isDurable = Boolean.parseBoolean(subDurable); } String msgSelector = properties.getProperty(JMSConstants.PARAM_MSG_SELECTOR); if (msgSelector != null) { messageSelector = msgSelector; } this.connectionFactoryString = properties .getProperty(JMSConstants.CONNECTION_FACTORY_JNDI_NAME); if (connectionFactoryString == null || "".equals(connectionFactoryString)) { connectionFactoryString = "QueueConnectionFactory"; } this.destinationName = properties.getProperty(JMSConstants.DESTINATION_NAME); if (destinationName == null || "".equals(destinationName)) { destinationName = "QUEUE_" + System.currentTimeMillis(); } String strTransactedSession = properties.getProperty(JMSConstants.SESSION_TRANSACTED); if (strTransactedSession == null || "".equals(strTransactedSession) || !strTransactedSession.equals("true")) { transactedSession = false; } else if ("true".equals(strTransactedSession)) { transactedSession = true; } String strSessionAck = properties.getProperty(JMSConstants.SESSION_ACK); if (null == strSessionAck) { sessionAckMode = 1; } else if (strSessionAck.equals("AUTO_ACKNOWLEDGE")) { sessionAckMode = Session.AUTO_ACKNOWLEDGE; } else if (strSessionAck.equals("CLIENT_ACKNOWLEDGE")) { sessionAckMode = Session.CLIENT_ACKNOWLEDGE; } else if (strSessionAck.equals("DUPS_OK_ACKNOWLEDGE")) { sessionAckMode = Session.DUPS_OK_ACKNOWLEDGE; } else if (strSessionAck.equals("SESSION_TRANSACTED")) { sessionAckMode = Session.SESSION_TRANSACTED; } else { sessionAckMode = 1; } createConnectionFactory(); } public ConnectionFactory getConnectionFactory() { if (this.connectionFactory != null) { return this.connectionFactory; } return createConnectionFactory(); } private ConnectionFactory createConnectionFactory() { if (this.connectionFactory != null) { return this.connectionFactory; } if (ctx == null) { return null; } try { if (this.destinationType.equals(JMSConstants.JMSDestinationType.QUEUE)) { this.connectionFactory = (QueueConnectionFactory) ctx .lookup(this.connectionFactoryString); } else if (this.destinationType.equals(JMSConstants.JMSDestinationType.TOPIC)) { this.connectionFactory = (TopicConnectionFactory) ctx .lookup(this.connectionFactoryString); } } catch (NamingException e) { logger.error("Naming exception while obtaining connection factory for '" + this.connectionFactoryString + "'", e); } return this.connectionFactory; } public Connection getConnection() { return createConnection(); } public Connection createConnection() { if (connectionFactory == null) { logger.error("Connection cannot be establish to the broker. Please check the broker libs provided."); return null; } Connection connection = null; try { if ( "1.1".equals(jmsSpec) ) { if (this.destinationType.equals(JMSConstants.JMSDestinationType.QUEUE)) { connection = ((QueueConnectionFactory) (this.connectionFactory)).createQueueConnection(); } else if (this.destinationType.equals(JMSConstants.JMSDestinationType.TOPIC)) { connection = ((TopicConnectionFactory) (this.connectionFactory)).createTopicConnection(); } if (isDurable) { connection.setClientID(clientId); } return connection; } else { QueueConnectionFactory qConFac = null; TopicConnectionFactory tConFac = null; if (this.destinationType.equals(JMSConstants.JMSDestinationType.QUEUE)) { qConFac = (QueueConnectionFactory) this.connectionFactory; } else { tConFac = (TopicConnectionFactory) this.connectionFactory; } if (qConFac != null) { connection = qConFac.createQueueConnection(); } else if (tConFac != null) { connection = tConFac.createTopicConnection(); } if (isDurable && !isSharedSubscription) { connection.setClientID(clientId); } return connection; } } catch (JMSException e) { logger.error("JMS Exception while creating connection through factory '" + this.connectionFactoryString + "' " + e.getMessage(), e); // Need to close the connection in the case if durable subscriptions if (connection != null) { try { connection.close(); } catch (Exception ex) { } } } return null; } public Connection createConnection(String userName, String password) { Connection connection = null; try { if ( JMSConstants.JMS_SPEC_VERSION_1_1.equals(jmsSpec) ) { if (this.destinationType.equals(JMSConstants.JMSDestinationType.QUEUE)) { connection = ((QueueConnectionFactory) (this.connectionFactory)) .createQueueConnection(userName, password); } else if (this.destinationType.equals(JMSConstants.JMSDestinationType.TOPIC)) { connection = ((TopicConnectionFactory) (this.connectionFactory)) .createTopicConnection(userName, password); } if (isDurable) { connection.setClientID(clientId); } return connection; } else { QueueConnectionFactory qConFac = null; TopicConnectionFactory tConFac = null; if (this.destinationType.equals(JMSConstants.JMSDestinationType.QUEUE)) { qConFac = (QueueConnectionFactory) this.connectionFactory; } else { tConFac = (TopicConnectionFactory) this.connectionFactory; } if (qConFac != null) { connection = qConFac.createQueueConnection(userName, password); } else if (tConFac != null) { connection = tConFac.createTopicConnection(userName, password); } if (isDurable && !isSharedSubscription) { connection.setClientID(clientId); } return connection; } } catch (JMSException e) { logger.error("JMS Exception while creating connection through factory '" + this.connectionFactoryString + "' " + e.getMessage()); // Need to close the connection in the case if durable subscriptions if (connection != null) { try { connection.close(); } catch (Exception ex) { } } } return null; } public QueueConnection createQueueConnection() throws JMSException { try { return ((QueueConnectionFactory) (this.connectionFactory)).createQueueConnection(); } catch (JMSException e) { logger.error("JMS Exception while creating queue connection through factory '" + this.connectionFactoryString + "' " + e.getMessage(), e); } return null; } public QueueConnection createQueueConnection(String userName, String password) throws JMSException { try { return ((QueueConnectionFactory) (this.connectionFactory)).createQueueConnection( userName, password); } catch (JMSException e) { logger.error("JMS Exception while creating queue connection through factory '" + this.connectionFactoryString + "' " + e.getMessage(), e); } return null; } public TopicConnection createTopicConnection() throws JMSException { try { return ((TopicConnectionFactory) (this.connectionFactory)).createTopicConnection(); } catch (JMSException e) { logger.error("JMS Exception while creating topic connection through factory '" + this.connectionFactoryString + "' " + e.getMessage(), e); } return null; } public TopicConnection createTopicConnection(String userName, String password) throws JMSException { try { return ((TopicConnectionFactory) (this.connectionFactory)).createTopicConnection( userName, password); } catch (JMSException e) { logger.error("JMS Exception while creating topic connection through factory '" + this.connectionFactoryString + "' " + e.getMessage(), e); } return null; } public Destination getDestination(Session session) { if (this.destination != null) { return this.destination; } return createDestination(session); } public MessageConsumer createMessageConsumer(Session session, Destination destination) { try { if ( JMSConstants.JMS_SPEC_VERSION_2_0.equals(jmsSpec) && isSharedSubscription ){ if (isDurable) { return session.createSharedDurableConsumer((Topic) destination, subscriptionName, messageSelector); } else { return session.createSharedConsumer((Topic) destination, subscriptionName, messageSelector); } } else if( (JMSConstants.JMS_SPEC_VERSION_1_1.equals(jmsSpec)) || ( JMSConstants.JMS_SPEC_VERSION_2_0.equals( jmsSpec) && !isSharedSubscription ) ){ if (isDurable) { return session.createDurableSubscriber((Topic) destination, subscriptionName, messageSelector, noPubSubLocal); } else { return session.createConsumer(destination, messageSelector); } } else { if (this.destinationType.equals(JMSConstants.JMSDestinationType.QUEUE)) { return ((QueueSession) session).createReceiver((Queue) destination, messageSelector); } else { if (isDurable) { return ((TopicSession) session).createDurableSubscriber((Topic) destination, subscriptionName, messageSelector, noPubSubLocal); } else { return ((TopicSession) session).createSubscriber((Topic) destination, messageSelector, false); } } } } catch (JMSException e) { logger.error("JMS Exception while creating consumer. " + e.getMessage(), e); } return null; } /** * This is a JMS spec independent method to create a MessageProducer. Please be cautious when * making any changes * * @param session JMS session * @param destination the Destination * @param isQueue is the Destination a queue? * @param jmsSpec11 should we use JMS 1.1 API ? * @return a MessageProducer to send messages to the given Destination * @throws JMSException on errors, to be handled and logged by the caller */ public MessageProducer createProducer(Session session, Destination destination, Boolean isQueue) throws JMSException { if ( "2.0".equals(jmsSpec) || "1.1".equals(jmsSpec) || isQueue == null) { return session.createProducer(destination); } else { if (isQueue) { return ((QueueSession) session).createSender((Queue) destination); } else { return ((TopicSession) session).createPublisher((Topic) destination); } } } private Destination createDestination(Session session) { this.destination = createDestination(session, this.destinationName); return this.destination; } public Destination createDestination(Session session, String destinationName) { Destination destination = null; try { if (this.destinationType.equals(JMSConstants.JMSDestinationType.QUEUE)) { destination = JMSUtils.lookupDestination(ctx, destinationName, JMSConstants.DESTINATION_TYPE_QUEUE); } else if (this.destinationType.equals(JMSConstants.JMSDestinationType.TOPIC)) { destination = JMSUtils.lookupDestination(ctx, destinationName, JMSConstants.DESTINATION_TYPE_TOPIC); } } catch (NameNotFoundException e) { if (logger.isDebugEnabled()) { logger.debug("Could not find destination '" + destinationName + "' on connection factory for '" + this.connectionFactoryString + "'. " + e.getMessage()); logger.debug("Creating destination '" + destinationName + "' on connection factory for '" + this.connectionFactoryString + "."); } try { if (this.destinationType.equals(JMSConstants.JMSDestinationType.QUEUE)) { destination = (Queue) session.createQueue(destinationName); } else if (this.destinationType.equals(JMSConstants.JMSDestinationType.TOPIC)) { destination = (Topic) session.createTopic(destinationName); } if (logger.isDebugEnabled()) { logger.debug("Created '" + destinationName + "' on connection factory for '" + this.connectionFactoryString + "'."); } } catch (JMSException e1) { logger.error("Could not find nor create '" + destinationName + "' on connection factory for '" + this.connectionFactoryString + "'. " + e1.getMessage(), e1); } } catch (NamingException e) { logger.error("Naming exception while obtaining connection factory for '" + this.connectionFactoryString + "' " + e.getMessage(), e); } return destination; } public Session getSession(Connection connection) { return createSession(connection); } protected Session createSession(Connection connection) { try { if ( JMSConstants.JMS_SPEC_VERSION_1_1.equals(jmsSpec) || JMSConstants.JMS_SPEC_VERSION_2_0.equals( jmsSpec) ) { return connection.createSession(transactedSession, sessionAckMode); } else { if (this.destinationType.equals(JMSConstants.JMSDestinationType.QUEUE)) { return (QueueSession) ((QueueConnection) (connection)).createQueueSession( transactedSession, sessionAckMode); } else if (this.destinationType.equals(JMSConstants.JMSDestinationType.TOPIC)) { return (TopicSession) ((TopicConnection) (connection)).createTopicSession( transactedSession, sessionAckMode); } } } catch (JMSException e) { logger.error("JMS Exception while obtaining session for factory '" + this.connectionFactoryString + "' " + e.getMessage(), e); } return null; } public void start(Connection connection) { try { connection.start(); } catch (JMSException e) { logger.error("JMS Exception while starting connection for factory '" + this.connectionFactoryString + "' " + e.getMessage(), e); } } public void stop(Connection connection) { try { connection.stop(); } catch (JMSException e) { logger.error("JMS Exception while stopping connection for factory '" + this.connectionFactoryString + "' " + e.getMessage(), e); } } public boolean closeConnection(Connection connection) { try { connection.close(); return true; } catch (JMSException e) { logger.error("JMS Exception while closing the connection."); } return false; } public Context getContext() { return this.ctx; } public JMSConstants.JMSDestinationType getDestinationType() { return this.destinationType; } public String getConnectionFactoryString() { return connectionFactoryString; } public boolean isTransactedSession() { return transactedSession; } public int getSessionAckMode() { return sessionAckMode; } public javax.jms.JMSContext createContext() { return connectionFactory.createContext(); } public javax.jms.JMSContext createContext(int sessionMode) { return connectionFactory.createContext(sessionMode); } public javax.jms.JMSContext createContext(String userName, String password) { return connectionFactory.createContext(userName, password); } public javax.jms.JMSContext createContext(String userName, String password, int sessionMode) { return connectionFactory.createContext(userName, password, sessionMode); } }