diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/ConditionLogUtils.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/ConditionLogUtils.java deleted file mode 100644 index 8ff9b2d76e..0000000000 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/ConditionLogUtils.java +++ /dev/null @@ -1,46 +0,0 @@ -/* - * Copyright 2012-2013 the original author or authors. - * - * Licensed 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.springframework.boot.autoconfigure.condition; - -import org.apache.commons.logging.Log; -import org.springframework.core.type.AnnotatedTypeMetadata; -import org.springframework.core.type.ClassMetadata; -import org.springframework.core.type.MethodMetadata; - -/** - * General utilities for constructing {@code @Conditional} log messages. - * - * @author Dave Syer - */ -public abstract class ConditionLogUtils { - - public static String getPrefix(Log logger, AnnotatedTypeMetadata metadata) { - String prefix = ""; - if (logger.isDebugEnabled()) { - prefix = metadata instanceof ClassMetadata ? "Processing " - + ((ClassMetadata) metadata).getClassName() + ". " - : (metadata instanceof MethodMetadata ? "Processing " - + getMethodName((MethodMetadata) metadata) + ". " : ""); - } - return prefix; - } - - private static String getMethodName(MethodMetadata metadata) { - return metadata.getDeclaringClassName() + "#" + metadata.getMethodName(); - } - -} diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnBeanCondition.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnBeanCondition.java index 2f0bc82dd7..24aa63de7e 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnBeanCondition.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnBeanCondition.java @@ -21,8 +21,6 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.List; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.BeanFactory; import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; @@ -45,32 +43,25 @@ import org.springframework.util.ReflectionUtils.MethodCallback; * @author Phillip Webb * @author Dave Syer */ -class OnBeanCondition implements ConfigurationCondition { +class OnBeanCondition extends SpringBootCondition implements ConfigurationCondition { private static final String[] NO_BEANS = {}; - private final Log logger = LogFactory.getLog(getClass()); - @Override public ConfigurationPhase getConfigurationPhase() { return ConfigurationPhase.REGISTER_BEAN; } @Override - public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { - - String checking = ConditionLogUtils.getPrefix(this.logger, metadata); + public Outcome getMatchOutcome(ConditionContext context, + AnnotatedTypeMetadata metadata) { if (metadata.isAnnotated(ConditionalOnBean.class.getName())) { BeanSearchSpec spec = new BeanSearchSpec(context, metadata, ConditionalOnBean.class); List matching = getMatchingBeans(context, spec); if (matching.isEmpty()) { - if (this.logger.isDebugEnabled()) { - this.logger.debug(checking + " @ConditionalOnBean " + spec - + " found no beans (search terminated with matches=false)"); - } - return false; + return Outcome.noMatch("@ConditionalOnBean " + spec + " found no beans"); } } @@ -79,16 +70,12 @@ class OnBeanCondition implements ConfigurationCondition { ConditionalOnMissingBean.class); List matching = getMatchingBeans(context, spec); if (!matching.isEmpty()) { - if (this.logger.isDebugEnabled()) { - this.logger.debug(checking + " @ConditionalOnMissingBean " + spec - + " found the following " + matching - + " (search terminated with matches=false)"); - } - return false; + return Outcome.noMatch("@ConditionalOnMissingBean " + spec + + " found the following " + matching); } } - return true; + return Outcome.match(); } private List getMatchingBeans(ConditionContext context, BeanSearchSpec beans) { diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnClassCondition.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnClassCondition.java index 3bdc97f51a..800ad96ef5 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnClassCondition.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnClassCondition.java @@ -20,8 +20,6 @@ import java.util.Iterator; import java.util.LinkedList; import java.util.List; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata; @@ -36,14 +34,11 @@ import org.springframework.util.StringUtils; * @see ConditionalOnClass * @see ConditionalOnMissingClass */ -class OnClassCondition implements Condition { - - private static Log logger = LogFactory.getLog(OnClassCondition.class); +class OnClassCondition extends SpringBootCondition { @Override - public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { - - String checking = ConditionLogUtils.getPrefix(logger, metadata); + public Outcome getMatchOutcome(ConditionContext context, + AnnotatedTypeMetadata metadata) { MultiValueMap onClasses = getAttributes(metadata, ConditionalOnClass.class); @@ -51,13 +46,8 @@ class OnClassCondition implements Condition { List missing = getMatchingClasses(onClasses, MatchType.MISSING, context); if (!missing.isEmpty()) { - if (logger.isDebugEnabled()) { - logger.debug(checking - + "Required @ConditionalOnClass classes not found: " - + StringUtils.collectionToCommaDelimitedString(missing) - + " (search terminated with matches=false)"); - } - return false; + return Outcome.noMatch("required @ConditionalOnClass classes not found: " + + StringUtils.collectionToCommaDelimitedString(missing)); } } @@ -67,20 +57,12 @@ class OnClassCondition implements Condition { List present = getMatchingClasses(onMissingClasses, MatchType.PRESENT, context); if (!present.isEmpty()) { - if (logger.isDebugEnabled()) { - logger.debug(checking - + "Required @ConditionalOnMissing classes found: " - + StringUtils.collectionToCommaDelimitedString(present) - + " (search terminated with matches=false)"); - } - return false; + return Outcome.noMatch("required @ConditionalOnMissing classes found: " + + StringUtils.collectionToCommaDelimitedString(present)); } } - if (logger.isDebugEnabled()) { - logger.debug(checking + "Match result is: true"); - } - return true; + return Outcome.match(); } private MultiValueMap getAttributes(AnnotatedTypeMetadata metadata, diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnExpressionCondition.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnExpressionCondition.java index ce9cc37522..b24cc412e8 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnExpressionCondition.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnExpressionCondition.java @@ -16,12 +16,9 @@ package org.springframework.boot.autoconfigure.condition; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.config.BeanExpressionContext; import org.springframework.beans.factory.config.BeanExpressionResolver; import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; -import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.context.expression.StandardBeanExpressionResolver; import org.springframework.core.type.AnnotatedTypeMetadata; @@ -33,32 +30,21 @@ import org.springframework.core.type.ClassMetadata; * @author Dave Syer * @see ConditionalOnExpression */ -public class OnExpressionCondition implements Condition { - - private static Log logger = LogFactory.getLog(OnExpressionCondition.class); +public class OnExpressionCondition extends SpringBootCondition { @Override - public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + public Outcome getMatchOutcome(ConditionContext context, + AnnotatedTypeMetadata metadata) { - String checking = ConditionLogUtils.getPrefix(logger, metadata); - - String value = (String) metadata.getAnnotationAttributes( + String expression = (String) metadata.getAnnotationAttributes( ConditionalOnExpression.class.getName()).get("value"); - if (!value.startsWith("#{")) { + if (!expression.startsWith("#{")) { // For convenience allow user to provide bare expression with no #{} wrapper - value = "#{" + value + "}"; - } - if (logger.isDebugEnabled()) { - StringBuilder builder = new StringBuilder(checking) - .append("Evaluating expression"); - if (metadata instanceof ClassMetadata) { - builder.append(" on " + ((ClassMetadata) metadata).getClassName()); - } - builder.append(": " + value); - logger.debug(builder.toString()); + expression = "#{" + expression + "}"; } + // Explicitly allow environment placeholders inside the expression - value = context.getEnvironment().resolvePlaceholders(value); + expression = context.getEnvironment().resolvePlaceholders(expression); ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); BeanExpressionResolver resolver = beanFactory.getBeanExpressionResolver(); BeanExpressionContext expressionContext = (beanFactory != null) ? new BeanExpressionContext( @@ -66,11 +52,14 @@ public class OnExpressionCondition implements Condition { if (resolver == null) { resolver = new StandardBeanExpressionResolver(); } - boolean result = (Boolean) resolver.evaluate(value, expressionContext); - if (logger.isDebugEnabled()) { - logger.debug(checking + "Finished matching and result is matches=" + result); + boolean result = (Boolean) resolver.evaluate(expression, expressionContext); + + StringBuilder message = new StringBuilder("SpEL expression"); + if (metadata instanceof ClassMetadata) { + message.append(" on " + ((ClassMetadata) metadata).getClassName()); } - return result; + message.append(": " + expression); + return new Outcome(result, message.toString()); } } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnResourceCondition.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnResourceCondition.java index 8a4aba44e5..47777f5919 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnResourceCondition.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnResourceCondition.java @@ -19,8 +19,6 @@ package org.springframework.boot.autoconfigure.condition; import java.util.ArrayList; import java.util.List; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.io.DefaultResourceLoader; @@ -35,43 +33,29 @@ import org.springframework.util.MultiValueMap; * @author Dave Syer * @see ConditionalOnResource */ -class OnResourceCondition implements Condition { - - private static Log logger = LogFactory.getLog(OnResourceCondition.class); +class OnResourceCondition extends SpringBootCondition { private ResourceLoader defaultResourceLoader = new DefaultResourceLoader(); @Override - public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { - - String checking = ConditionLogUtils.getPrefix(logger, metadata); - + public Outcome getMatchOutcome(ConditionContext context, + AnnotatedTypeMetadata metadata) { MultiValueMap attributes = metadata.getAllAnnotationAttributes( ConditionalOnResource.class.getName(), true); - ResourceLoader loader = context.getResourceLoader() == null ? this.defaultResourceLoader - : context.getResourceLoader(); if (attributes != null) { + ResourceLoader loader = context.getResourceLoader() == null ? this.defaultResourceLoader + : context.getResourceLoader(); List locations = new ArrayList(); collectValues(locations, attributes.get("resources")); Assert.isTrue(locations.size() > 0, "@ConditionalOnResource annotations must specify at least one resource location"); for (String location : locations) { - if (logger.isDebugEnabled()) { - logger.debug(checking + "Checking for resource: " + location); - } if (!loader.getResource(location).exists()) { - if (logger.isDebugEnabled()) { - logger.debug(checking + "Resource not found: " + location - + " (search terminated with matches=false)"); - } - return false; + return Outcome.noMatch("resource not found: " + location); } } } - if (logger.isDebugEnabled()) { - logger.debug(checking + "Match result is: true"); - } - return true; + return Outcome.match(); } private void collectValues(List names, List values) { diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnWebApplicationCondition.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnWebApplicationCondition.java index c2177b05a9..7ea1072294 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnWebApplicationCondition.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/OnWebApplicationCondition.java @@ -16,8 +16,6 @@ package org.springframework.boot.autoconfigure.condition; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.core.type.AnnotatedTypeMetadata; @@ -34,51 +32,46 @@ import org.springframework.web.context.support.StandardServletEnvironment; * @see ConditionalOnWebApplication * @see ConditionalOnNotWebApplication */ -class OnWebApplicationCondition implements Condition { +class OnWebApplicationCondition extends SpringBootCondition { private static final String WEB_CONTEXT_CLASS = "org.springframework.web.context.support.GenericWebApplicationContext"; - private static Log logger = LogFactory.getLog(OnWebApplicationCondition.class); - @Override - public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { - boolean webContextRequired = metadata + public Outcome getMatchOutcome(ConditionContext context, + AnnotatedTypeMetadata metadata) { + boolean webApplicationRequired = metadata .isAnnotated(ConditionalOnWebApplication.class.getName()); - boolean webApplication = isWebApplication(context, metadata); - return (webContextRequired ? webApplication : !webApplication); + Outcome webApplication = isWebApplication(context, metadata); + + if (webApplicationRequired && !webApplication.isMatch()) { + return Outcome.noMatch(webApplication.getMessage()); + } + + if (!webApplicationRequired && webApplication.isMatch()) { + return Outcome.noMatch(webApplication.getMessage()); + } + + return Outcome.match(webApplication.getMessage()); } - private boolean isWebApplication(ConditionContext context, + private Outcome isWebApplication(ConditionContext context, AnnotatedTypeMetadata metadata) { - String checking = ConditionLogUtils.getPrefix(logger, metadata); if (!ClassUtils.isPresent(WEB_CONTEXT_CLASS, context.getClassLoader())) { - if (logger.isDebugEnabled()) { - logger.debug(checking + "web application classes not found"); - } - return false; + return Outcome.noMatch("web application classes not found"); } if (context.getBeanFactory() != null) { String[] scopes = context.getBeanFactory().getRegisteredScopeNames(); if (ObjectUtils.containsElement(scopes, "session")) { - if (logger.isDebugEnabled()) { - logger.debug(checking + "found web application scope"); - } - return true; + return Outcome.match("found web application 'session' scope"); } } if (context.getEnvironment() instanceof StandardServletEnvironment) { - if (logger.isDebugEnabled()) { - logger.debug(checking + "found web application environment"); - } - return true; + return Outcome.match("found web application StandardServletEnvironment"); } - if (logger.isDebugEnabled()) { - logger.debug(checking + "is not a web application"); - } - return false; + return Outcome.noMatch("not a web application"); } } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/SpringBootCondition.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/SpringBootCondition.java new file mode 100644 index 0000000000..4ab8c9ca22 --- /dev/null +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/condition/SpringBootCondition.java @@ -0,0 +1,140 @@ +/* + * Copyright 2012-2013 the original author or authors. + * + * Licensed 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.springframework.boot.autoconfigure.condition; + +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogFactory; +import org.springframework.context.annotation.Condition; +import org.springframework.context.annotation.ConditionContext; +import org.springframework.core.type.AnnotatedTypeMetadata; +import org.springframework.core.type.ClassMetadata; +import org.springframework.core.type.MethodMetadata; +import org.springframework.util.ClassUtils; +import org.springframework.util.StringUtils; + +/** + * Base of all {@link Condition} implementations used with Spring Boot. Provides sensible + * logging to help the user diagnose what classes are loaded. + * + * @author Phillip Webb + */ +public abstract class SpringBootCondition implements Condition { + + private final Log logger = LogFactory.getLog(getClass()); + + @Override + public final boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + Outcome result = getMatchOutcome(context, metadata); + if (!result.isMatch()) { + // Log non-matching conditions at debug + if (this.logger.isDebugEnabled()) { + this.logger.debug(getMessage(metadata, result)); + } + return false; + } + + // Log matching conditions at trace + if (this.logger.isTraceEnabled()) { + this.logger.trace(getMessage(metadata, result)); + } + return true; + } + + private StringBuilder getMessage(AnnotatedTypeMetadata metadata, Outcome result) { + StringBuilder message = new StringBuilder(); + message.append("Condition "); + message.append(ClassUtils.getShortName(getClass())); + message.append(" on "); + if (metadata instanceof ClassMetadata) { + ClassMetadata classMetadata = (ClassMetadata) metadata; + message.append(classMetadata.getClassName()); + } + else if (metadata instanceof MethodMetadata) { + MethodMetadata methodMetadata = (MethodMetadata) metadata; + message.append(methodMetadata.getDeclaringClassName()); + message.append("#"); + message.append(methodMetadata.getMethodName()); + } + message.append(result.isMatch() ? " matched" : "did not match"); + if (StringUtils.hasLength(result.getMessage())) { + message.append(" due to "); + message.append(result.getMessage()); + } + return message; + } + + /** + * Determine the outcome of the match along with suitable log output. + */ + public abstract Outcome getMatchOutcome(ConditionContext context, + AnnotatedTypeMetadata metadata); + + protected final boolean anyMatches(ConditionContext context, + AnnotatedTypeMetadata metadata, Condition... conditions) { + for (Condition condition : conditions) { + if (matches(context, metadata, condition)) { + return true; + } + } + return false; + } + + protected final boolean matches(ConditionContext context, + AnnotatedTypeMetadata metadata, Condition condition) { + if (condition instanceof SpringBootCondition) { + return ((SpringBootCondition) condition).getMatchOutcome(context, metadata) + .isMatch(); + } + return condition.matches(context, metadata); + } + + /** + * Outcome for a match, including log message. + */ + protected final static class Outcome { + + private final boolean match; + + private final String message; + + public Outcome(boolean match, String message) { + this.match = match; + this.message = message; + } + + public boolean isMatch() { + return this.match; + } + + public String getMessage() { + return this.message; + } + + public static Outcome match() { + return match(null); + } + + public static Outcome match(String message) { + return new Outcome(true, message); + } + + public static Outcome noMatch(String message) { + return new Outcome(false, message); + } + + } +} diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration.java index a59b501734..774aae3824 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceAutoConfiguration.java @@ -29,9 +29,9 @@ import org.springframework.beans.factory.BeanFactoryUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionLogUtils; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; +import org.springframework.boot.autoconfigure.condition.SpringBootCondition; import org.springframework.context.ApplicationContext; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Condition; @@ -39,6 +39,7 @@ import org.springframework.context.annotation.ConditionContext; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import org.springframework.core.env.Environment; import org.springframework.core.io.Resource; import org.springframework.core.type.AnnotatedTypeMetadata; import org.springframework.jdbc.core.JdbcOperations; @@ -55,6 +56,7 @@ import org.springframework.util.StringUtils; * {@link EnableAutoConfiguration Auto-configuration} for {@link DataSource}. * * @author Dave Syer + * @author Phillip Webb */ @Configuration @ConditionalOnClass(EmbeddedDatabaseType.class /* Spring JDBC */) @@ -85,7 +87,7 @@ public class DataSourceAutoConfiguration { } @Configuration - @Conditional(DataSourceAutoConfiguration.SomeDatabaseCondition.class) + @Conditional(DataSourceAutoConfiguration.DatabaseCondition.class) protected static class JdbcTemplateConfiguration { @Autowired(required = false) @@ -134,119 +136,39 @@ public class DataSourceAutoConfiguration { } } - static class SomeDatabaseCondition implements Condition { + static abstract class NonEmbeddedDatabaseCondition extends SpringBootCondition { - private Log logger = LogFactory.getLog(getClass()); - - private Condition tomcatCondition = new TomcatDatabaseCondition(); - - private Condition dbcpCondition = new BasicDatabaseCondition(); - - private Condition embeddedCondition = new EmbeddedDatabaseCondition(); + protected abstract String getDataSourceClassName(); @Override - public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { + public Outcome getMatchOutcome(ConditionContext context, + AnnotatedTypeMetadata metadata) { - String checking = ConditionLogUtils.getPrefix(this.logger, metadata); + if (!ClassUtils.isPresent(getDataSourceClassName(), context.getClassLoader())) { + return Outcome.noMatch(getDataSourceClassName() + + " DataSource class not found"); + } - if (this.tomcatCondition.matches(context, metadata) - || this.dbcpCondition.matches(context, metadata) - || this.embeddedCondition.matches(context, metadata)) { - if (this.logger.isDebugEnabled()) { - this.logger.debug(checking + "Existing auto database " - + "detected: match result true"); - } - return true; + String driverClassName = getDriverClassName(context.getEnvironment()); + if (driverClassName == null) { + return Outcome.noMatch("no database driver"); } - if (BeanFactoryUtils.beanNamesForTypeIncludingAncestors( - context.getBeanFactory(), DataSource.class, true, false).length > 0) { - if (this.logger.isDebugEnabled()) { - this.logger.debug(checking + "Existing bean configured database " - + "detected: match result true"); - } - return true; + + String url = getUrl(context.getEnvironment()); + if (url == null) { + return Outcome.noMatch("no database URL"); } - if (this.logger.isDebugEnabled()) { - this.logger.debug(checking + "Existing bean configured database not " - + "detected: match result false"); + + if (ClassUtils.isPresent(driverClassName, context.getClassLoader())) { + return Outcome.match("found database driver " + driverClassName); } - return false; + + return Outcome.match("missing database driver " + driverClassName); } - } - - static class TomcatDatabaseCondition extends NonEmbeddedDatabaseCondition { - - @Override - protected String getDataSourecClassName() { - return "org.apache.tomcat.jdbc.pool.DataSource"; - } - - } - - static class BasicDatabaseCondition extends NonEmbeddedDatabaseCondition { - - private Condition condition = new TomcatDatabaseCondition(); - - @Override - protected String getDataSourecClassName() { - return "org.apache.commons.dbcp.BasicDataSource"; - } - - @Override - public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { - if (this.condition.matches(context, metadata)) { - return false; // prefer Tomcat pool - } - return super.matches(context, metadata); - } - } - - static abstract class NonEmbeddedDatabaseCondition implements Condition { - - private Log logger = LogFactory.getLog(getClass()); - - protected abstract String getDataSourecClassName(); - - @Override - public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { - - String checking = ConditionLogUtils.getPrefix(this.logger, metadata); - - if (!ClassUtils.isPresent(getDataSourecClassName(), null)) { - if (this.logger.isDebugEnabled()) { - this.logger.debug(checking + "Tomcat DataSource pool not found"); - } - return false; - } - - String driverClassName = getDriverClassName(context, checking); - String url = getUrl(context); - - if (driverClassName != null && url != null - && ClassUtils.isPresent(driverClassName, null)) { - if (this.logger.isDebugEnabled()) { - this.logger.debug(checking + "Driver class " + driverClassName - + " found"); - } - return true; - } - - if (this.logger.isDebugEnabled()) { - this.logger.debug(checking + "Driver class " + driverClassName - + " not found"); - } - return false; - } - - private String getDriverClassName(ConditionContext context, String checking) { - String driverClassName = context.getEnvironment().getProperty( - "spring.database.driverClassName"); - if (this.logger.isDebugEnabled()) { - this.logger.debug(checking - + "Spring JDBC detected (embedded database type is " - + EmbeddedDatabaseConfiguration.getEmbeddedDatabaseType() + ")."); - } + private String getDriverClassName(Environment environment) { + String driverClassName = environment == null ? null : environment + .getProperty("spring.database.driverClassName"); if (driverClassName == null) { driverClassName = EmbeddedDatabaseConfiguration .getEmbeddedDatabaseDriverClass(EmbeddedDatabaseConfiguration @@ -255,8 +177,9 @@ public class DataSourceAutoConfiguration { return driverClassName; } - private String getUrl(ConditionContext context) { - String url = context.getEnvironment().getProperty("spring.database.url"); + private String getUrl(Environment environment) { + String url = (environment == null ? null : environment + .getProperty("spring.database.url")); if (url == null) { url = EmbeddedDatabaseConfiguration .getEmbeddedDatabaseUrl(EmbeddedDatabaseConfiguration @@ -266,34 +189,78 @@ public class DataSourceAutoConfiguration { } } - static class EmbeddedDatabaseCondition implements Condition { - - private Log logger = LogFactory.getLog(getClass()); + static class BasicDatabaseCondition extends NonEmbeddedDatabaseCondition { private Condition tomcatCondition = new TomcatDatabaseCondition(); - private Condition dbcpCondition = new BasicDatabaseCondition(); + @Override + protected String getDataSourceClassName() { + return "org.apache.commons.dbcp.BasicDataSource"; + } @Override - public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { - - String checking = ConditionLogUtils.getPrefix(this.logger, metadata); - - if (this.tomcatCondition.matches(context, metadata) - || this.dbcpCondition.matches(context, metadata)) { - if (this.logger.isDebugEnabled()) { - this.logger.debug(checking + "Existing non-embedded " - + "database detected: match result false"); - } - return false; + public Outcome getMatchOutcome(ConditionContext context, + AnnotatedTypeMetadata metadata) { + if (matches(context, metadata, this.tomcatCondition)) { + return Outcome.noMatch("tomcat DataSource"); } - if (this.logger.isDebugEnabled()) { - this.logger.debug(checking - + "Spring JDBC detected (embedded database type is " - + EmbeddedDatabaseConfiguration.getEmbeddedDatabaseType() + ")."); - } - return EmbeddedDatabaseConfiguration.getEmbeddedDatabaseType() != null; + return super.getMatchOutcome(context, metadata); } } + static class TomcatDatabaseCondition extends NonEmbeddedDatabaseCondition { + + @Override + protected String getDataSourceClassName() { + return "org.apache.tomcat.jdbc.pool.DataSource"; + } + + } + + static class EmbeddedDatabaseCondition extends SpringBootCondition { + + private SpringBootCondition tomcatCondition = new TomcatDatabaseCondition(); + + private SpringBootCondition dbcpCondition = new BasicDatabaseCondition(); + + @Override + public Outcome getMatchOutcome(ConditionContext context, + AnnotatedTypeMetadata metadata) { + if (anyMatches(context, metadata, this.tomcatCondition, this.dbcpCondition)) { + return Outcome.noMatch("existing non-embedded database detected"); + } + EmbeddedDatabaseType type = EmbeddedDatabaseConfiguration + .getEmbeddedDatabaseType(); + if (type == null) { + return Outcome.noMatch("no embedded database detected"); + } + return Outcome.match("embedded database " + type + " detected"); + } + } + + static class DatabaseCondition extends SpringBootCondition { + + private SpringBootCondition tomcatCondition = new TomcatDatabaseCondition(); + + private SpringBootCondition dbcpCondition = new BasicDatabaseCondition(); + + private SpringBootCondition embeddedCondition = new EmbeddedDatabaseCondition(); + + @Override + public Outcome getMatchOutcome(ConditionContext context, + AnnotatedTypeMetadata metadata) { + + if (anyMatches(context, metadata, this.tomcatCondition, this.dbcpCondition, + this.embeddedCondition)) { + return Outcome.match("existing auto database detected"); + } + + if (BeanFactoryUtils.beanNamesForTypeIncludingAncestors( + context.getBeanFactory(), DataSource.class, true, false).length > 0) { + return Outcome.match("Existing bean configured database detected"); + } + + return Outcome.noMatch("no existing bean configured database"); + } + } } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/EmbeddedServletContainerAutoConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/EmbeddedServletContainerAutoConfiguration.java index 2c84425ce8..951912f4d1 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/EmbeddedServletContainerAutoConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/web/EmbeddedServletContainerAutoConfiguration.java @@ -21,8 +21,6 @@ import java.util.Arrays; import javax.servlet.Servlet; import org.apache.catalina.startup.Tomcat; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.eclipse.jetty.server.Server; import org.eclipse.jetty.util.Loader; import org.springframework.beans.BeansException; @@ -33,10 +31,10 @@ import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; import org.springframework.beans.factory.support.BeanDefinitionRegistry; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.boot.autoconfigure.EnableAutoConfiguration; -import org.springframework.boot.autoconfigure.condition.ConditionLogUtils; import org.springframework.boot.autoconfigure.condition.ConditionalOnClass; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.condition.SearchStrategy; +import org.springframework.boot.autoconfigure.condition.SpringBootCondition; import org.springframework.boot.autoconfigure.web.EmbeddedServletContainerAutoConfiguration.EmbeddedServletContainerCustomizerBeanPostProcessorRegistrar; import org.springframework.boot.context.embedded.EmbeddedServletContainerCustomizerBeanPostProcessor; import org.springframework.boot.context.embedded.EmbeddedServletContainerFactory; @@ -44,7 +42,6 @@ import org.springframework.boot.context.embedded.ServletContextInitializer; import org.springframework.boot.context.embedded.jetty.JettyEmbeddedServletContainerFactory; import org.springframework.boot.context.embedded.tomcat.TomcatEmbeddedServletContainerFactory; import org.springframework.context.annotation.Bean; -import org.springframework.context.annotation.Condition; import org.springframework.context.annotation.ConditionContext; import org.springframework.context.annotation.Conditional; import org.springframework.context.annotation.Configuration; @@ -149,42 +146,24 @@ public class EmbeddedServletContainerAutoConfiguration { } } - private static class DefaultServletCondition implements Condition { - - private static Log logger = LogFactory.getLog(DefaultServletCondition.class); + private static class DefaultServletCondition extends SpringBootCondition { @Override - public boolean matches(ConditionContext context, AnnotatedTypeMetadata metadata) { - - String checking = ConditionLogUtils.getPrefix(logger, metadata); + public Outcome getMatchOutcome(ConditionContext context, + AnnotatedTypeMetadata metadata) { ConfigurableListableBeanFactory beanFactory = context.getBeanFactory(); String[] beans = beanFactory.getBeanNamesForType(DispatcherServlet.class, false, false); if (beans.length == 0) { - if (logger.isDebugEnabled()) { - logger.debug(checking - + "No DispatcherServlet found (search terminated with matches=true)"); - } - // No dispatcher servlet so no need to ask further questions - return true; + return Outcome.match("no DispatcherServlet found"); } if (Arrays.asList(beans).contains(DEFAULT_DISPATCHER_SERVLET_BEAN_NAME)) { - if (logger.isDebugEnabled()) { - logger.debug(checking + "DispatcherServlet found and named " - + DEFAULT_DISPATCHER_SERVLET_BEAN_NAME - + " (search terminated with matches=false)"); - } - // An existing bean with the default name - return false; + return Outcome.noMatch("found DispatcherServlet named " + + DEFAULT_DISPATCHER_SERVLET_BEAN_NAME); } - if (logger.isDebugEnabled()) { - logger.debug(checking - + "Multiple DispatcherServlets found and none is named " - + DEFAULT_DISPATCHER_SERVLET_BEAN_NAME - + " (search terminated with matches=true)"); - } - return true; + return Outcome.match("multiple DispatcherServlets found and none is named " + + DEFAULT_DISPATCHER_SERVLET_BEAN_NAME); } }