001/*
002 * Copyright 2012-2016 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.cassandra;
018
019import java.util.List;
020
021import com.datastax.driver.core.Cluster;
022import com.datastax.driver.core.QueryOptions;
023import com.datastax.driver.core.SocketOptions;
024import com.datastax.driver.core.policies.LoadBalancingPolicy;
025import com.datastax.driver.core.policies.ReconnectionPolicy;
026import com.datastax.driver.core.policies.RetryPolicy;
027
028import org.springframework.beans.BeanUtils;
029import org.springframework.beans.factory.ObjectProvider;
030import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
031import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
032import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
033import org.springframework.boot.context.properties.EnableConfigurationProperties;
034import org.springframework.context.annotation.Bean;
035import org.springframework.context.annotation.Configuration;
036import org.springframework.util.StringUtils;
037
038/**
039 * {@link EnableAutoConfiguration Auto-configuration} for Cassandra.
040 *
041 * @author Julien Dubois
042 * @author Phillip Webb
043 * @author Eddú Meléndez
044 * @author Stephane Nicoll
045 * @since 1.3.0
046 */
047@Configuration
048@ConditionalOnClass({ Cluster.class })
049@EnableConfigurationProperties(CassandraProperties.class)
050public class CassandraAutoConfiguration {
051
052        private final CassandraProperties properties;
053
054        private final List<ClusterBuilderCustomizer> builderCustomizers;
055
056        public CassandraAutoConfiguration(CassandraProperties properties,
057                        ObjectProvider<List<ClusterBuilderCustomizer>> builderCustomizers) {
058                this.properties = properties;
059                this.builderCustomizers = builderCustomizers.getIfAvailable();
060        }
061
062        @Bean
063        @ConditionalOnMissingBean
064        public Cluster cluster() {
065                CassandraProperties properties = this.properties;
066                Cluster.Builder builder = Cluster.builder()
067                                .withClusterName(properties.getClusterName())
068                                .withPort(properties.getPort());
069                if (properties.getUsername() != null) {
070                        builder.withCredentials(properties.getUsername(), properties.getPassword());
071                }
072                if (properties.getCompression() != null) {
073                        builder.withCompression(properties.getCompression());
074                }
075                if (properties.getLoadBalancingPolicy() != null) {
076                        LoadBalancingPolicy policy = instantiate(properties.getLoadBalancingPolicy());
077                        builder.withLoadBalancingPolicy(policy);
078                }
079                builder.withQueryOptions(getQueryOptions());
080                if (properties.getReconnectionPolicy() != null) {
081                        ReconnectionPolicy policy = instantiate(properties.getReconnectionPolicy());
082                        builder.withReconnectionPolicy(policy);
083                }
084                if (properties.getRetryPolicy() != null) {
085                        RetryPolicy policy = instantiate(properties.getRetryPolicy());
086                        builder.withRetryPolicy(policy);
087                }
088                builder.withSocketOptions(getSocketOptions());
089                if (properties.isSsl()) {
090                        builder.withSSL();
091                }
092                String points = properties.getContactPoints();
093                builder.addContactPoints(StringUtils.commaDelimitedListToStringArray(points));
094
095                customize(builder);
096                return builder.build();
097        }
098
099        private void customize(Cluster.Builder builder) {
100                if (this.builderCustomizers != null) {
101                        for (ClusterBuilderCustomizer customizer : this.builderCustomizers) {
102                                customizer.customize(builder);
103                        }
104                }
105        }
106
107        public static <T> T instantiate(Class<T> type) {
108                return BeanUtils.instantiate(type);
109        }
110
111        private QueryOptions getQueryOptions() {
112                QueryOptions options = new QueryOptions();
113                CassandraProperties properties = this.properties;
114                if (properties.getConsistencyLevel() != null) {
115                        options.setConsistencyLevel(properties.getConsistencyLevel());
116                }
117                if (properties.getSerialConsistencyLevel() != null) {
118                        options.setSerialConsistencyLevel(properties.getSerialConsistencyLevel());
119                }
120                options.setFetchSize(properties.getFetchSize());
121                return options;
122        }
123
124        private SocketOptions getSocketOptions() {
125                SocketOptions options = new SocketOptions();
126                options.setConnectTimeoutMillis(this.properties.getConnectTimeoutMillis());
127                options.setReadTimeoutMillis(this.properties.getReadTimeoutMillis());
128                return options;
129        }
130
131}