/* * Bitronix Transaction Manager * * Copyright (c) 2010, Bitronix Software. * * This copyrighted material is made available to anyone wishing to use, modify, * copy, or redistribute it subject to the terms and conditions of the GNU * Lesser General Public License, as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License * for more details. * * You should have received a copy of the GNU Lesser General Public License * along with this distribution; if not, write to: * Free Software Foundation, Inc. * 51 Franklin Street, Fifth Floor * Boston, MA 02110-1301 USA */ package bitronix.tm.resource.jms; import javax.jms.JMSException; import javax.jms.XAConnection; import javax.jms.XAConnectionFactory; import javax.naming.Context; import javax.naming.InitialContext; import javax.naming.NamingException; import javax.rmi.PortableRemoteObject; import java.util.Hashtable; import java.util.Properties; /** * {@link XAConnectionFactory} implementation that wraps another {@link XAConnectionFactory} implementation available * in some JNDI tree. * * @author lorban */ public class JndiXAConnectionFactory implements XAConnectionFactory { private volatile String initialContextFactory; private volatile String providerUrl; private volatile String urlPkgPrefixes; private volatile String name; private volatile String securityPrincipal; private volatile String securityCredentials; private volatile Properties extraJndiProperties = new Properties(); private volatile boolean narrowJndiObject = false; private volatile XAConnectionFactory wrappedFactory; public JndiXAConnectionFactory() { } /** * The {@link Context#INITIAL_CONTEXT_FACTORY} of the JNDI {@link Context} used to fetch the {@link XAConnectionFactory}. * @return the {@link Context#INITIAL_CONTEXT_FACTORY} value. */ public String getInitialContextFactory() { return initialContextFactory; } /** * Set the {@link Context#INITIAL_CONTEXT_FACTORY} of the JNDI {@link Context} used to fetch the {@link XAConnectionFactory}. * If not set, the {@link Context} is created without the environment parameter, using the default constructor. This means * <i>all other properties (providerUrl, urlPkgPrefixes, extraJndiProperties...) are then ignored.</i> * @param initialContextFactory the {@link Context#INITIAL_CONTEXT_FACTORY} value. */ public void setInitialContextFactory(String initialContextFactory) { this.initialContextFactory = initialContextFactory; } /** * The {@link Context#PROVIDER_URL} of the JNDI {@link Context} used to fetch the {@link XAConnectionFactory}. * @return the {@link Context#PROVIDER_URL} value. */ public String getProviderUrl() { return providerUrl; } /** * Set the {@link Context#PROVIDER_URL} of the JNDI {@link Context} used to fetch the {@link XAConnectionFactory}. * @param providerUrl the {@link Context#PROVIDER_URL} value. */ public void setProviderUrl(String providerUrl) { this.providerUrl = providerUrl; } /** * The {@link Context#URL_PKG_PREFIXES} of the JNDI {@link Context} used to fetch the {@link XAConnectionFactory}. * @return the {@link Context#URL_PKG_PREFIXES} value. */ public String getUrlPkgPrefixes() { return urlPkgPrefixes; } /** * Set the {@link Context#URL_PKG_PREFIXES} of the JNDI {@link Context} used to fetch the {@link XAConnectionFactory}. * @param urlPkgPrefixes the {@link Context#URL_PKG_PREFIXES} value. */ public void setUrlPkgPrefixes(String urlPkgPrefixes) { this.urlPkgPrefixes = urlPkgPrefixes; } /** * The {@link Context#SECURITY_PRINCIPAL} of the JNDI {@link Context} used to fetch the {@link XAConnectionFactory}. * @return the {@link Context#SECURITY_PRINCIPAL} value. */ public String getSecurityPrincipal() { return securityPrincipal; } /** * Set the {@link Context#SECURITY_PRINCIPAL} of the JNDI {@link Context} used to fetch the {@link XAConnectionFactory}. * If {@link Context#INITIAL_CONTEXT_FACTORY} and {@link Context#PROVIDER_URL} are not set, this value is ignored. * @param securityPrincipal the {@link Context#SECURITY_PRINCIPAL} value. */ public void setSecurityPrincipal(String securityPrincipal) { this.securityPrincipal = securityPrincipal; } /** * The {@link Context#SECURITY_CREDENTIALS} of the JNDI {@link Context} used to fetch the {@link XAConnectionFactory}. * @return the {@link Context#SECURITY_CREDENTIALS} value. */ public String getSecurityCredentials() { return securityCredentials; } /** * Set the {@link Context#SECURITY_CREDENTIALS} of the JNDI {@link Context} used to fetch the {@link XAConnectionFactory}. * If {@link Context#INITIAL_CONTEXT_FACTORY} and {@link Context#PROVIDER_URL} are not set, this value is ignored. * @param securityCredentials the {@link Context#SECURITY_CREDENTIALS} value. */ public void setSecurityCredentials(String securityCredentials) { this.securityCredentials = securityCredentials; } /** * The JNDI name under which the {@link XAConnectionFactory} is available. * @return The JNDI name. */ public String getName() { return name; } /** * Set the JNDI name under which the {@link XAConnectionFactory} is available. * @param name the JNDI name. */ public void setName(String name) { this.name = name; } /** * The extra JNDI environment properties added the the {@link InitialContext}'s environment upon creation. * @return The extra JNDI environment properties. */ public Properties getExtraJndiProperties() { return extraJndiProperties; } /** * Set the extra JNDI environment properties added the the {@link InitialContext}'s environment upon creation. * @param extraJndiProperties The extra JNDI environment properties. */ public void setExtraJndiProperties(Properties extraJndiProperties) { this.extraJndiProperties = extraJndiProperties; } /** * Should {@link PortableRemoteObject#narrow(Object, Class)} be applied on the object looked up from * JNDI before trying to cast it to {@link XAConnectionFactory} ? * @return true if the object should be narrowed, false otherwise. */ public boolean isNarrowJndiObject() { return narrowJndiObject; } /** * Set if {@link PortableRemoteObject#narrow(Object, Class)} should be applied on the object looked up from * JNDI before trying to cast it to {@link XAConnectionFactory} ? * @param narrowJndiObject true if the object should be narrowed, false otherwise. */ public void setNarrowJndiObject(boolean narrowJndiObject) { this.narrowJndiObject = narrowJndiObject; } protected void init() throws NamingException { if (wrappedFactory != null) return; Context ctx; if (!isEmpty(initialContextFactory)) { Hashtable<Object, Object> env = new Hashtable<Object, Object>(); env.put(Context.INITIAL_CONTEXT_FACTORY, initialContextFactory); if (!isEmpty(providerUrl)) env.put(Context.PROVIDER_URL, providerUrl); if (!isEmpty(urlPkgPrefixes)) env.put(Context.URL_PKG_PREFIXES, urlPkgPrefixes); if (!isEmpty(securityPrincipal)) env.put(Context.SECURITY_PRINCIPAL, securityPrincipal); if (!isEmpty(securityCredentials)) env.put(Context.SECURITY_CREDENTIALS, securityCredentials); if (!extraJndiProperties.isEmpty()) env.putAll(extraJndiProperties); ctx = new InitialContext(env); } else { ctx = new InitialContext(); } try { Object lookedUpObject = ctx.lookup(name); if (narrowJndiObject) { wrappedFactory = (XAConnectionFactory) PortableRemoteObject.narrow(lookedUpObject, XAConnectionFactory.class); } else { wrappedFactory = (XAConnectionFactory) lookedUpObject; } } finally { ctx.close(); } } public XAConnection createXAConnection() throws JMSException { try { init(); return wrappedFactory.createXAConnection(); } catch (NamingException ex) { throw (JMSException) new JMSException("error looking up wrapped XAConnectionFactory at " + name).initCause(ex); } } public XAConnection createXAConnection(String userName, String password) throws JMSException { try { init(); return wrappedFactory.createXAConnection(userName, password); } catch (NamingException ex) { throw (JMSException) new JMSException("error looking up wrapped XAConnectionFactory at " + name).initCause(ex); } } private static boolean isEmpty(String str) { return str == null || str.trim().equals(""); } }