001/*
002 * Copyright 2012-2018 the original author or authors.
003 *
004 * Licensed under the Apache License, Version 2.0 (the "License");
005 * you may not use this file except in compliance with the License.
006 * You may obtain a copy of the License at
007 *
008 *      http://www.apache.org/licenses/LICENSE-2.0
009 *
010 * Unless required by applicable law or agreed to in writing, software
011 * distributed under the License is distributed on an "AS IS" BASIS,
012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013 * See the License for the specific language governing permissions and
014 * limitations under the License.
015 */
016
017package org.springframework.boot.autoconfigure.jms;
018
019import java.util.Arrays;
020
021import javax.jms.ConnectionFactory;
022import javax.naming.NamingException;
023
024import org.springframework.boot.autoconfigure.AutoConfigureBefore;
025import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
026import org.springframework.boot.autoconfigure.condition.AnyNestedCondition;
027import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
028import org.springframework.boot.autoconfigure.condition.ConditionalOnJndi;
029import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
030import org.springframework.boot.autoconfigure.condition.ConditionalOnProperty;
031import org.springframework.boot.autoconfigure.jms.JndiConnectionFactoryAutoConfiguration.JndiOrPropertyCondition;
032import org.springframework.boot.context.properties.EnableConfigurationProperties;
033import org.springframework.context.annotation.Bean;
034import org.springframework.context.annotation.Conditional;
035import org.springframework.context.annotation.Configuration;
036import org.springframework.jms.core.JmsTemplate;
037import org.springframework.jndi.JndiLocatorDelegate;
038import org.springframework.util.StringUtils;
039
040/**
041 * {@link EnableAutoConfiguration Auto-configuration} for JMS provided from JNDI.
042 *
043 * @author Phillip Webb
044 * @since 1.2.0
045 */
046@Configuration
047@AutoConfigureBefore(JmsAutoConfiguration.class)
048@ConditionalOnClass(JmsTemplate.class)
049@ConditionalOnMissingBean(ConnectionFactory.class)
050@Conditional(JndiOrPropertyCondition.class)
051@EnableConfigurationProperties(JmsProperties.class)
052public class JndiConnectionFactoryAutoConfiguration {
053
054        // Keep these in sync with the condition below
055        private static final String[] JNDI_LOCATIONS = { "java:/JmsXA",
056                        "java:/XAConnectionFactory" };
057
058        private final JmsProperties properties;
059
060        private final JndiLocatorDelegate jndiLocatorDelegate;
061
062        public JndiConnectionFactoryAutoConfiguration(JmsProperties properties) {
063                this.properties = properties;
064                this.jndiLocatorDelegate = JndiLocatorDelegate.createDefaultResourceRefLocator();
065        }
066
067        @Bean
068        public ConnectionFactory connectionFactory() throws NamingException {
069                if (StringUtils.hasLength(this.properties.getJndiName())) {
070                        return this.jndiLocatorDelegate.lookup(this.properties.getJndiName(),
071                                        ConnectionFactory.class);
072                }
073                return findJndiConnectionFactory();
074        }
075
076        private ConnectionFactory findJndiConnectionFactory() {
077                for (String name : JNDI_LOCATIONS) {
078                        try {
079                                return this.jndiLocatorDelegate.lookup(name, ConnectionFactory.class);
080                        }
081                        catch (NamingException ex) {
082                                // Swallow and continue
083                        }
084                }
085                throw new IllegalStateException(
086                                "Unable to find ConnectionFactory in JNDI locations "
087                                                + Arrays.asList(JNDI_LOCATIONS));
088        }
089
090        /**
091         * Condition for JNDI name or a specific property.
092         */
093        static class JndiOrPropertyCondition extends AnyNestedCondition {
094
095                JndiOrPropertyCondition() {
096                        super(ConfigurationPhase.PARSE_CONFIGURATION);
097                }
098
099                @ConditionalOnJndi({ "java:/JmsXA", "java:/XAConnectionFactory" })
100                static class Jndi {
101
102                }
103
104                @ConditionalOnProperty(prefix = "spring.jms", name = "jndi-name")
105                static class Property {
106
107                }
108
109        }
110
111}