diff --git a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/reader/MetricRegistryMetricReader.java b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/reader/MetricRegistryMetricReader.java index d3d4487c92b..1ce9373e151 100644 --- a/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/reader/MetricRegistryMetricReader.java +++ b/spring-boot-actuator/src/main/java/org/springframework/boot/actuate/metrics/reader/MetricRegistryMetricReader.java @@ -57,7 +57,7 @@ public class MetricRegistryMetricReader implements MetricReader, MetricRegistryL private static Log logger = LogFactory.getLog(MetricRegistryMetricReader.class); - private static final Map, Set> NUMBER_KEYS = new ConcurrentHashMap, Set>(); + private static final Map, Set> numberKeys = new ConcurrentHashMap, Set>(); private final Object monitor = new Object(); @@ -129,17 +129,16 @@ public class MetricRegistryMetricReader implements MetricReader, MetricRegistryL @Override public void onGaugeAdded(String name, Gauge gauge) { - if (gauge.getValue() instanceof Number) { - this.names.put(name, name); - synchronized (this.monitor) { - this.reverse.add(name, name); + if (!(gauge.getValue() instanceof Number)) { + if (logger.isDebugEnabled()) { + logger.debug("Ignoring gauge '" + name + "' (" + gauge + + ") as its value is not a Number"); } return; } - - if (logger.isDebugEnabled()) { - logger.debug("Ignoring gauge '" + name + "' (" + gauge - + ") as its value is not a Number"); + this.names.put(name, name); + synchronized (this.monitor) { + this.reverse.add(name, name); } } @@ -225,11 +224,9 @@ public class MetricRegistryMetricReader implements MetricReader, MetricRegistryL private void remove(String name) { List keys; - synchronized (this.monitor) { keys = this.reverse.remove(name); } - if (keys != null) { for (String key : keys) { this.names.remove(name + "." + key); @@ -238,7 +235,7 @@ public class MetricRegistryMetricReader implements MetricReader, MetricRegistryL } private static Set getNumberKeys(Object metric) { - Set result = NUMBER_KEYS.get(metric.getClass()); + Set result = numberKeys.get(metric.getClass()); if (result == null) { result = new HashSet(); } @@ -249,7 +246,7 @@ public class MetricRegistryMetricReader implements MetricReader, MetricRegistryL result.add(descriptor.getName()); } } - NUMBER_KEYS.put(metric.getClass(), result); + numberKeys.put(metric.getClass(), result); } return result; } diff --git a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/reader/MetricRegistryMetricReaderTests.java b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/reader/MetricRegistryMetricReaderTests.java index 39f4e7bd465..1858435a6b7 100644 --- a/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/reader/MetricRegistryMetricReaderTests.java +++ b/spring-boot-actuator/src/test/java/org/springframework/boot/actuate/metrics/reader/MetricRegistryMetricReaderTests.java @@ -31,7 +31,7 @@ import static org.hamcrest.Matchers.nullValue; import static org.junit.Assert.assertThat; /** - * Tests for {@link MetricRegistryMetricReader} + * Tests for {@link MetricRegistryMetricReader}. * * @author Andy Wilkinson */ @@ -73,4 +73,5 @@ public class MetricRegistryMetricReaderTests { this.metricRegistry.remove("test"); assertThat(this.metricReader.findOne("test"), is(nullValue())); } + } diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceInitializer.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceInitializer.java index e7a15c419af..c0bcf36f7c8 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceInitializer.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/jdbc/DataSourceInitializer.java @@ -1,5 +1,5 @@ /* - * Copyright 2012-2014 the original author or authors. + * Copyright 2012-2015 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. @@ -63,8 +63,8 @@ class DataSourceInitializer implements ApplicationListener 0) { - this.dataSource = applicationContext.getBean(DataSource.class); + if (this.applicationContext.getBeanNamesForType(DataSource.class, false, false).length > 0) { + this.dataSource = this.applicationContext.getBean(DataSource.class); } if (this.dataSource == null) { logger.debug("No DataSource found so not initializing"); diff --git a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/AuthenticationManagerConfiguration.java b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/AuthenticationManagerConfiguration.java index 74cd06b8a7b..45c2b846e8e 100644 --- a/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/AuthenticationManagerConfiguration.java +++ b/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/security/AuthenticationManagerConfiguration.java @@ -22,12 +22,14 @@ import java.util.Set; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.NoSuchBeanDefinitionException; import org.springframework.beans.factory.SmartInitializingSingleton; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.boot.autoconfigure.condition.ConditionalOnBean; import org.springframework.boot.autoconfigure.condition.ConditionalOnMissingBean; import org.springframework.boot.autoconfigure.security.SecurityProperties.User; import org.springframework.context.ApplicationContext; +import org.springframework.context.ApplicationListener; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Primary; @@ -70,55 +72,33 @@ public class AuthenticationManagerConfiguration { @Bean @Primary - public AuthenticationManager authenticationManager(AuthenticationConfiguration auth) - throws Exception { - return auth.getAuthenticationManager(); + public AuthenticationManager authenticationManager( + AuthenticationConfiguration configuration) throws Exception { + return configuration.getAuthenticationManager(); } @Bean - public static BootDefaultingAuthenticationConfigurerAdapter bootDefaultingAuthenticationConfigurerAdapter( - SecurityProperties security, List dependencies) { - return new BootDefaultingAuthenticationConfigurerAdapter(security); - } - - @Component - protected static class AuthenticationManagerConfigurationListener implements - SmartInitializingSingleton { - - @Autowired - private AuthenticationEventPublisher authenticationEventPublisher; - - @Autowired - private ApplicationContext context; - - @Override - public void afterSingletonsInstantiated() { - if (this.context.getBeanNamesForType(AuthenticationManager.class).length == 0) { - return; - } - AuthenticationManager manager = this.context - .getBean(AuthenticationManager.class); - if (manager instanceof ProviderManager) { - ((ProviderManager) manager) - .setAuthenticationEventPublisher(this.authenticationEventPublisher); - } - } - + public static SpringBootAuthenticationConfigurerAdapter springBootAuthenticationConfigurerAdapter( + SecurityProperties securityProperties, List dependencies) { + return new SpringBootAuthenticationConfigurerAdapter(securityProperties); } /** - * We must add {@link BootDefaultingAuthenticationConfigurerAdapter} in the init phase - * of the last {@link GlobalAuthenticationConfigurerAdapter}. The reason is that the - * typical flow is something like: + * {@link GlobalAuthenticationConfigurerAdapter} to apply + * {@link DefaultInMemoryUserDetailsManagerConfigurer}. We must apply + * {@link DefaultInMemoryUserDetailsManagerConfigurer} in the init phase of the last + * {@link GlobalAuthenticationConfigurerAdapter}. The reason is that the typical flow + * is something like: + * *
    *
  • A * {@link GlobalAuthenticationConfigurerAdapter#init(AuthenticationManagerBuilder)} * exists that adds a {@link SecurityConfigurer} to the - * {@link AuthenticationManagerBuilder}
  • + * {@link AuthenticationManagerBuilder}. *
  • * {@link AuthenticationManagerConfiguration#init(AuthenticationManagerBuilder)} adds - * BootDefaultingAuthenticationConfigurerAdapter so it is after the - * {@link SecurityConfigurer} in the first step
  • + * {@link SpringBootAuthenticationConfigurerAdapter} so it is after the + * {@link SecurityConfigurer} in the first step. *
  • We then can default an {@link AuthenticationProvider} if necessary. Note we can * only invoke the * {@link AuthenticationManagerBuilder#authenticationProvider(AuthenticationProvider)} @@ -128,70 +108,106 @@ public class AuthenticationManagerConfiguration { *
*/ @Order(Ordered.LOWEST_PRECEDENCE - 100) - private static class BootDefaultingAuthenticationConfigurerAdapter extends + private static class SpringBootAuthenticationConfigurerAdapter extends GlobalAuthenticationConfigurerAdapter { - private final SecurityProperties security; + + private final SecurityProperties securityProperties; @Autowired - public BootDefaultingAuthenticationConfigurerAdapter(SecurityProperties security) { - this.security = security; + public SpringBootAuthenticationConfigurerAdapter( + SecurityProperties securityProperties) { + this.securityProperties = securityProperties; } @Override public void init(AuthenticationManagerBuilder auth) throws Exception { - auth.apply(new DefaultingInMemoryUserDetailsManagerConfigurer(this.security)); + auth.apply(new DefaultInMemoryUserDetailsManagerConfigurer( + this.securityProperties)); } - /** - * This is necessary to delay adding the default user. - * - *
    - *
  • A GlobalAuthenticationConfigurerAdapter will initialize the - * AuthenticationManagerBuilder with a Configurer which will be after any - * GlobalAuthenticationConfigurerAdapter
  • - *
  • BootDefaultingAuthenticationConfigurerAdapter will be invoked after all - * GlobalAuthenticationConfigurerAdapter, but before the Configurers that were - * added by other GlobalAuthenticationConfigurerAdapter instances
  • - *
  • BootDefaultingAuthenticationConfigurerAdapter will add - * DefaultingInMemoryUserDetailsManagerConfigurer after all Configurer instances
  • - *
  • All init methods will be invoked
  • - *
  • All configure methods will be invoked which is where the - * AuthenticationProvider instances are setup
  • - *
  • If no AuthenticationProviders were provided, - * DefaultingInMemoryUserDetailsManagerConfigurer will default the value
  • - *
- * - * @author Rob Winch - */ - private static class DefaultingInMemoryUserDetailsManagerConfigurer extends - InMemoryUserDetailsManagerConfigurer { - private final SecurityProperties security; - - public DefaultingInMemoryUserDetailsManagerConfigurer( - SecurityProperties security) { - this.security = security; + } + + /** + * {@link InMemoryUserDetailsManagerConfigurer} to add user details from + * {@link SecurityProperties}. This is necessary to delay adding the default user. + * + *
    + *
  • A {@link GlobalAuthenticationConfigurerAdapter} will initialize the + * {@link AuthenticationManagerBuilder} with a Configurer which will be after any + * {@link GlobalAuthenticationConfigurerAdapter}.
  • + *
  • {@link SpringBootAuthenticationConfigurerAdapter} will be invoked after all + * {@link GlobalAuthenticationConfigurerAdapter}, but before the Configurers that were + * added by other {@link GlobalAuthenticationConfigurerAdapter} instances.
  • + *
  • A {@link SpringBootAuthenticationConfigurerAdapter} will add + * {@link DefaultInMemoryUserDetailsManagerConfigurer} after all Configurer instances. + *
  • + *
  • All init methods will be invoked.
  • + *
  • All configure methods will be invoked which is where the + * {@link AuthenticationProvider} instances are setup.
  • + *
  • If no AuthenticationProviders were provided, + * {@link DefaultInMemoryUserDetailsManagerConfigurer} will default the value.
  • + *
+ */ + private static class DefaultInMemoryUserDetailsManagerConfigurer extends + InMemoryUserDetailsManagerConfigurer { + + private final SecurityProperties securityProperties; + + public DefaultInMemoryUserDetailsManagerConfigurer( + SecurityProperties securityProperties) { + this.securityProperties = securityProperties; + } + + @Override + public void configure(AuthenticationManagerBuilder auth) throws Exception { + if (auth.isConfigured()) { + return; + } + User user = this.securityProperties.getUser(); + if (user.isDefaultPassword()) { + logger.info("\n\nUsing default security password: " + user.getPassword() + + "\n"); } + Set roles = new LinkedHashSet(user.getRole()); + withUser(user.getName()).password(user.getPassword()).roles( + roles.toArray(new String[roles.size()])); + super.configure(auth); + } + + } - @Override - public void configure(AuthenticationManagerBuilder auth) throws Exception { - if (auth.isConfigured()) { - return; - } + /** + * {@link ApplicationListener} to autowire the {@link AuthenticationEventPublisher} + * into the {@link AuthenticationManager}. + */ + @Component + protected static class AuthenticationManagerConfigurationListener implements + SmartInitializingSingleton { - User user = this.security.getUser(); - if (user.isDefaultPassword()) { - logger.info("\n\nUsing default security password: " - + user.getPassword() + "\n"); - } + @Autowired + private AuthenticationEventPublisher eventPublisher; - Set roles = new LinkedHashSet(user.getRole()); - withUser(user.getName()).password(user.getPassword()).roles( - roles.toArray(new String[roles.size()])); + @Autowired + private ApplicationContext context; - super.configure(auth); + @Override + public void afterSingletonsInstantiated() { + try { + configureAuthenticationManager(this.context + .getBean(AuthenticationManager.class)); } + catch (NoSuchBeanDefinitionException ex) { + // Ignore + } + } + private void configureAuthenticationManager(AuthenticationManager manager) { + if (manager instanceof ProviderManager) { + ((ProviderManager) manager) + .setAuthenticationEventPublisher(this.eventPublisher); + } } } -} \ No newline at end of file + +} diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainer.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainer.java index e0d341c71c7..fd2c8928e3b 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainer.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/undertow/UndertowEmbeddedServletContainer.java @@ -141,27 +141,33 @@ public class UndertowEmbeddedServletContainer implements EmbeddedServletContaine } private Port getPortFromChannel(Object channel) { - Object tcpServer; - String protocol; + Object tcpServer = channel; + String protocol = "http"; Field sslContext = ReflectionUtils.findField(channel.getClass(), "sslContext"); if (sslContext != null) { - Field tcpServerField = ReflectionUtils.findField(channel.getClass(), - "tcpServer"); - ReflectionUtils.makeAccessible(tcpServerField); - tcpServer = ReflectionUtils.getField(tcpServerField, channel); + tcpServer = getTcpServer(channel); protocol = "https"; } - else { - tcpServer = channel; - protocol = "http"; + ServerSocket socket = getSocket(tcpServer); + if (socket != null) { + return new Port(socket.getLocalPort(), protocol); } + return null; + } + + private Object getTcpServer(Object channel) { + Field field = ReflectionUtils.findField(channel.getClass(), "tcpServer"); + ReflectionUtils.makeAccessible(field); + return ReflectionUtils.getField(field, channel); + } + + private ServerSocket getSocket(Object tcpServer) { Field socketField = ReflectionUtils.findField(tcpServer.getClass(), "socket"); - if (socketField != null) { - ReflectionUtils.makeAccessible(socketField); - return new Port(((ServerSocket) ReflectionUtils.getField(socketField, - tcpServer)).getLocalPort(), protocol); + if (socketField == null) { + return null; } - return null; + ReflectionUtils.makeAccessible(socketField); + return (ServerSocket) ReflectionUtils.getField(socketField, tcpServer); } @Override @@ -178,24 +184,32 @@ public class UndertowEmbeddedServletContainer implements EmbeddedServletContaine if (ports.isEmpty()) { return 0; } - return ports.get(0).portNumber; + return ports.get(0).getNumber(); } + /** + * An active undertow port. + */ private static class Port { - private final int portNumber; + private final int number; private final String protocol; - private Port(int portNumber, String protocol) { - this.portNumber = portNumber; + private Port(int number, String protocol) { + this.number = number; this.protocol = protocol; } + public int getNumber() { + return this.number; + } + @Override public String toString() { - return this.portNumber + " (" + this.protocol + ")"; + return this.number + " (" + this.protocol + ")"; } + } }