/* * 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 javax.resource.spi.ActivationSpec; import org.apache.tuscany.sca.binding.jms.JMSBindingException; /** * Abstracts away any JMS provide specific feature from the JMS binding * * @version $Rev$ $Date$ */ public class JMSResourceFactoryImpl implements JMSResourceFactory { protected String initialContextFactoryName; protected String connectionFactoryName = "ConnectionFactory"; protected String jndiURL; protected Connection connection; protected Context context; protected boolean isConnectionStarted; private Connection responseConnection; private String responseConnectionFactoryName; public JMSResourceFactoryImpl(String connectionFactoryName, String responseConnectionFactoryName, String initialContextFactoryName, String jndiURL) { if (connectionFactoryName != null && connectionFactoryName.trim().length() > 0) { this.connectionFactoryName = connectionFactoryName.trim(); } if (responseConnectionFactoryName != null && responseConnectionFactoryName.trim().length() > 0) { this.responseConnectionFactoryName = responseConnectionFactoryName.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#closeSession(javax.jms.Session) */ public void closeSession(Session session) throws JMSException { session.close(); } /* * (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; } } } } protected void createConnection() throws NamingException, JMSException { Object o = jndiLookUp(connectionFactoryName); if (o == null) { throw new JMSBindingException("connection factory not found: " + connectionFactoryName); } if (!(o instanceof ConnectionFactory)) { throw new JMSBindingException("JNDI resource '" + connectionFactoryName +"' is not a JMS ConnectionFactory"); } ConnectionFactory connectionFactory = (ConnectionFactory)o; connection = connectionFactory.createConnection(); } protected 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 */ protected 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 (destName == null) { 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 { if ( jndiName == null ) return null; return lookupDestination("dynamicQueues/" + jndiName); } protected Object jndiLookUp(String name) { Object o = null; try { o = getInitialContext().lookup("java:comp/env/" + name); } catch (Exception ex) { // ignore } if (o == null) { try { o = getInitialContext().lookup(name); } catch (NamingException ex) { // ignore } } return o; } public Session createResponseSession() throws JMSException, NamingException { return getResponseConnection().createSession(false, Session.AUTO_ACKNOWLEDGE); } public void closeResponseSession(Session session) throws JMSException { session.close(); } public Connection getResponseConnection() throws NamingException, JMSException { if (responseConnection == null) { if (responseConnectionFactoryName != null) { ConnectionFactory connectionFactory = (ConnectionFactory)jndiLookUp(responseConnectionFactoryName); if (connectionFactory == null) { throw new JMSBindingException("connection factory not found: " + responseConnectionFactoryName); } responseConnection = connectionFactory.createConnection(); } else { // if no response connection is defined in the SCDL use the request connection responseConnection = getConnection(); } } return responseConnection; } public void closeResponseConnection() throws JMSException { if (responseConnection != null && !responseConnection.equals(connection)) { try { responseConnection.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; } } } } public boolean isConnectionClosedAfterUse() { // It is assumed this resource factory is used in an environment // where the connection can be held for the life of the binding. return false; } public ActivationSpec lookupActivationSpec(String activationSpecName) { Object o = jndiLookUp(activationSpecName); if ( o == null ) return null; else if (o instanceof ActivationSpec) return (ActivationSpec) o; throw new JMSBindingException("Incorrect resource type for ActivationSpec: " + o.getClass().getName()); } }