001/*
002 * Copyright 2012-2017 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.session;
018
019import javax.annotation.PostConstruct;
020
021import org.springframework.beans.factory.ObjectProvider;
022import org.springframework.boot.autoconfigure.AutoConfigureAfter;
023import org.springframework.boot.autoconfigure.EnableAutoConfiguration;
024import org.springframework.boot.autoconfigure.condition.ConditionalOnClass;
025import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean;
026import org.springframework.boot.autoconfigure.condition.ConditionalOnWebApplication;
027import org.springframework.boot.autoconfigure.data.redis.RedisAutoConfiguration;
028import org.springframework.boot.autoconfigure.hazelcast.HazelcastAutoConfiguration;
029import org.springframework.boot.autoconfigure.jdbc.DataSourceAutoConfiguration;
030import org.springframework.boot.autoconfigure.jdbc.JdbcTemplateAutoConfiguration;
031import org.springframework.boot.autoconfigure.mongo.MongoAutoConfiguration;
032import org.springframework.boot.autoconfigure.session.SessionAutoConfiguration.SessionConfigurationImportSelector;
033import org.springframework.boot.autoconfigure.session.SessionAutoConfiguration.SessionRepositoryValidator;
034import org.springframework.boot.context.properties.EnableConfigurationProperties;
035import org.springframework.context.annotation.Configuration;
036import org.springframework.context.annotation.Import;
037import org.springframework.context.annotation.ImportSelector;
038import org.springframework.core.type.AnnotationMetadata;
039import org.springframework.session.Session;
040import org.springframework.session.SessionRepository;
041
042/**
043 * {@link EnableAutoConfiguration Auto-configuration} for Spring Session.
044 *
045 * @author Andy Wilkinson
046 * @author Tommy Ludwig
047 * @author EddĂș MelĂ©ndez
048 * @author Stephane Nicoll
049 * @since 1.4.0
050 */
051@Configuration
052@ConditionalOnMissingBean(SessionRepository.class)
053@ConditionalOnClass(Session.class)
054@ConditionalOnWebApplication
055@EnableConfigurationProperties(SessionProperties.class)
056@AutoConfigureAfter({ DataSourceAutoConfiguration.class, HazelcastAutoConfiguration.class,
057                JdbcTemplateAutoConfiguration.class, MongoAutoConfiguration.class,
058                RedisAutoConfiguration.class })
059@Import({ SessionConfigurationImportSelector.class, SessionRepositoryValidator.class })
060public class SessionAutoConfiguration {
061
062        /**
063         * {@link ImportSelector} to add {@link StoreType} configuration classes.
064         */
065        static class SessionConfigurationImportSelector implements ImportSelector {
066
067                @Override
068                public String[] selectImports(AnnotationMetadata importingClassMetadata) {
069                        StoreType[] types = StoreType.values();
070                        String[] imports = new String[types.length];
071                        for (int i = 0; i < types.length; i++) {
072                                imports[i] = SessionStoreMappings.getConfigurationClass(types[i]);
073                        }
074                        return imports;
075                }
076
077        }
078
079        /**
080         * Bean used to validate that a {@link SessionRepository} exists and provide a
081         * meaningful message if that's not the case.
082         */
083        static class SessionRepositoryValidator {
084
085                private SessionProperties sessionProperties;
086
087                private ObjectProvider<SessionRepository<?>> sessionRepositoryProvider;
088
089                SessionRepositoryValidator(SessionProperties sessionProperties,
090                                ObjectProvider<SessionRepository<?>> sessionRepositoryProvider) {
091                        this.sessionProperties = sessionProperties;
092                        this.sessionRepositoryProvider = sessionRepositoryProvider;
093                }
094
095                @PostConstruct
096                public void checkSessionRepository() {
097                        StoreType storeType = this.sessionProperties.getStoreType();
098                        if (storeType != StoreType.NONE
099                                        && this.sessionRepositoryProvider.getIfAvailable() == null) {
100                                if (storeType != null) {
101                                        throw new IllegalArgumentException("No session repository could be "
102                                                        + "auto-configured, check your configuration (session store "
103                                                        + "type is '" + storeType.name().toLowerCase() + "')");
104                                }
105                                throw new IllegalArgumentException("No Spring Session store is "
106                                                + "configured: set the 'spring.session.store-type' property");
107                        }
108                }
109
110        }
111
112}