From 4cf27efdbeea47f942adb986da3b7b35dbfc6f47 Mon Sep 17 00:00:00 2001 From: spencergibb Date: Fri, 18 Sep 2020 17:19:22 -0400 Subject: [PATCH] Moves common property source functionality to ZookeeperPropertySources.java --- ...ZookeeperConfigBootstrapConfiguration.java | 10 ++- .../config/ZookeeperConfigDataLoader.java | 14 +--- .../ZookeeperConfigDataLocationResolver.java | 41 ++------- .../ZookeeperPropertySourceLocator.java | 46 ++-------- .../config/ZookeeperPropertySources.java | 84 +++++++++++++++++++ ...keeperConfigDataLocationResolverTests.java | 5 +- ...tySourceLocatorNoApplicationNameTests.java | 4 +- 7 files changed, 115 insertions(+), 89 deletions(-) create mode 100644 spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperPropertySources.java diff --git a/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperConfigBootstrapConfiguration.java b/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperConfigBootstrapConfiguration.java index a34d60d1..91e64f87 100644 --- a/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperConfigBootstrapConfiguration.java +++ b/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperConfigBootstrapConfiguration.java @@ -24,6 +24,8 @@ import org.springframework.cloud.zookeeper.ZookeeperAutoConfiguration; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Import; +import org.springframework.core.env.Environment; +import org.springframework.util.StringUtils; /** * Bootstrap Configuration for Zookeeper Configuration. @@ -45,8 +47,12 @@ public class ZookeeperConfigBootstrapConfiguration { @Bean @ConditionalOnMissingBean - public ZookeeperConfigProperties zookeeperConfigProperties() { - return new ZookeeperConfigProperties(); + public ZookeeperConfigProperties zookeeperConfigProperties(Environment env) { + ZookeeperConfigProperties properties = new ZookeeperConfigProperties(); + if (StringUtils.isEmpty(properties.getName())) { + properties.setName(env.getProperty("spring.application.name", "application")); + } + return properties; } } diff --git a/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperConfigDataLoader.java b/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperConfigDataLoader.java index 134e532d..bc26262c 100644 --- a/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperConfigDataLoader.java +++ b/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperConfigDataLoader.java @@ -18,8 +18,6 @@ package org.springframework.cloud.zookeeper.config; import java.util.Collections; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; import org.apache.curator.framework.CuratorFramework; import org.springframework.boot.context.config.ConfigData; @@ -29,8 +27,6 @@ import org.springframework.boot.context.config.ConfigDataLocationNotFoundExcepti public class ZookeeperConfigDataLoader implements ConfigDataLoader { - private static final Log log = LogFactory.getLog(ZookeeperConfigDataLoader.class); - @Override public ConfigData load(ConfigDataLoaderContext context, ZookeeperConfigDataLocation location) { try { @@ -40,16 +36,8 @@ public class ZookeeperConfigDataLoader implements ConfigDataLoader { - private static final Log log = LogFactory.getLog(ZookeeperConfigDataLocationResolver.class); - /** * Zookeeper Config Data prefix. */ public static final String PREFIX = "zookeeper:"; + private final Log log; + + public ZookeeperConfigDataLocationResolver(Log log) { + this.log = log; + } + @Override public boolean isResolvable(ConfigDataLocationResolverContext context, String location) { if (!location.startsWith(PREFIX)) { @@ -94,8 +97,10 @@ public class ZookeeperConfigDataLocationResolver implements ConfigDataLocationRe context.getBootstrapContext().registerIfAbsent(CuratorFramework.class, InstanceSupplier .from(() -> curatorFramework(context.getBootstrapContext(), zookeeperProperties, optional))); + ZookeeperPropertySources sources = new ZookeeperPropertySources(properties, log); + List contexts = (locationUri == null || CollectionUtils.isEmpty(locationUri.getPathSegments())) - ? getAutomaticContexts(profiles, properties) : getCustomContexts(locationUri); + ? sources.getAutomaticContexts(profiles.getAccepted()) : getCustomContexts(locationUri); context.getBootstrapContext().addCloseListener(event -> { CuratorFramework curatorFramework = event.getBootstrapContext().get(CuratorFramework.class); @@ -122,27 +127,6 @@ public class ZookeeperConfigDataLocationResolver implements ConfigDataLocationRe return Arrays.asList(uriComponents.getPath().split(";")); } - protected List getAutomaticContexts(Profiles profiles, ZookeeperConfigProperties properties) { - String root = properties.getRoot(); - List contexts = new ArrayList<>(); - - String defaultContext = root + "/" + properties.getDefaultContext(); - contexts.add(defaultContext); - addProfiles(contexts, defaultContext, profiles, properties); - - StringBuilder baseContext = new StringBuilder(root); - if (!properties.getName().startsWith("/")) { - baseContext.append("/"); - } - // getName() defaults to ${spring.application.name} or application - baseContext.append(properties.getName()); - contexts.add(baseContext.toString()); - addProfiles(contexts, baseContext.toString(), profiles, properties); - - Collections.reverse(contexts); - return contexts; - } - @Nullable protected UriComponents parseLocation(String location) { String uri = location.substring(PREFIX.length()); @@ -158,13 +142,6 @@ public class ZookeeperConfigDataLocationResolver implements ConfigDataLocationRe return UriComponentsBuilder.fromUriString(uri).build(); } - private void addProfiles(List contexts, String baseContext, Profiles profiles, - ZookeeperConfigProperties properties) { - for (String profile : profiles.getAccepted()) { - contexts.add(baseContext + properties.getProfileSeparator() + profile); - } - } - protected CuratorFramework curatorFramework(ConfigurableBootstrapContext context, ZookeeperProperties properties, boolean optional) { diff --git a/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperPropertySourceLocator.java b/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperPropertySourceLocator.java index 82ca7e59..1755c197 100644 --- a/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperPropertySourceLocator.java +++ b/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperPropertySourceLocator.java @@ -16,7 +16,6 @@ package org.springframework.cloud.zookeeper.config; -import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; import java.util.List; @@ -32,8 +31,7 @@ import org.springframework.core.env.CompositePropertySource; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.Environment; import org.springframework.core.env.PropertySource; -import org.springframework.util.ReflectionUtils; -import org.springframework.util.StringUtils; +import org.springframework.util.Assert; /** * Zookeeper provides a locate(Environment environment) { if (environment instanceof ConfigurableEnvironment) { ConfigurableEnvironment env = (ConfigurableEnvironment) environment; - String appName = properties.getName(); - if (StringUtils.isEmpty(appName)) { - // use default "application" (which config client does) - appName = env.getProperty("spring.application.name", "application"); - if (appName.equals("application")) { - log.warn("spring.application.name is not set. Using default of 'application'"); - } - } + List profiles = Arrays.asList(env.getActiveProfiles()); - String root = this.properties.getRoot(); - this.contexts = new ArrayList<>(); - - String defaultContext = root + "/" + this.properties.getDefaultContext(); - this.contexts.add(defaultContext); - addProfiles(this.contexts, defaultContext, profiles); - - StringBuilder baseContext = new StringBuilder(root); - if (!appName.startsWith("/")) { - baseContext.append("/"); - } - baseContext.append(appName); - this.contexts.add(baseContext.toString()); - addProfiles(this.contexts, baseContext.toString(), profiles); + ZookeeperPropertySources sources = new ZookeeperPropertySources(properties, log); + this.contexts = sources.getAutomaticContexts(profiles); CompositePropertySource composite = new CompositePropertySource("zookeeper"); Collections.reverse(this.contexts); for (String propertySourceContext : this.contexts) { - try { - PropertySource propertySource = create(propertySourceContext); - composite.addPropertySource(propertySource); - // TODO: howto call close when /refresh - } - catch (Exception e) { - if (this.properties.isFailFast()) { - ReflectionUtils.rethrowRuntimeException(e); - } - else { - log.warn("Unable to load zookeeper config from " - + propertySourceContext, e); - } - } + PropertySource propertySource = sources.createPropertySource(propertySourceContext, true, this.curator); + composite.addPropertySource(propertySource); } return composite; diff --git a/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperPropertySources.java b/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperPropertySources.java new file mode 100644 index 00000000..d7988268 --- /dev/null +++ b/spring-cloud-zookeeper-config/src/main/java/org/springframework/cloud/zookeeper/config/ZookeeperPropertySources.java @@ -0,0 +1,84 @@ +/* + * Copyright 2015-2020 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 + * + * https://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.cloud.zookeeper.config; + +import java.util.ArrayList; +import java.util.Collections; +import java.util.List; + +import org.apache.commons.logging.Log; +import org.apache.curator.framework.CuratorFramework; + +public class ZookeeperPropertySources { + private final ZookeeperConfigProperties properties; + private final Log log; + + public ZookeeperPropertySources(ZookeeperConfigProperties properties, Log log) { + this.properties = properties; + this.log = log; + } + + public List getAutomaticContexts(List profiles) { + String root = properties.getRoot(); + List contexts = new ArrayList<>(); + + String defaultContext = root + "/" + properties.getDefaultContext(); + contexts.add(defaultContext); + addProfiles(contexts, defaultContext, profiles); + + StringBuilder baseContext = new StringBuilder(root); + if (!properties.getName().startsWith("/")) { + baseContext.append("/"); + } + // getName() defaults to ${spring.application.name} or application + baseContext.append(properties.getName()); + contexts.add(baseContext.toString()); + addProfiles(contexts, baseContext.toString(), profiles); + + Collections.reverse(contexts); + return contexts; + } + + private void addProfiles(List contexts, String baseContext, List profiles) { + for (String profile : profiles) { + contexts.add(baseContext + properties.getProfileSeparator() + profile); + } + } + + public ZookeeperPropertySource createPropertySource(String context, boolean optional, CuratorFramework curator) { + try { + return new ZookeeperPropertySource(context, curator); + // TODO: howto call close when /refresh + } + catch (Exception e) { + if (this.properties.isFailFast() || !optional) { + throw new ZookeeperPropertySourceNotFoundException(e); + } + else { + log.warn("Unable to load zookeeper config from " + context, e); + } + } + return null; + } + + static class ZookeeperPropertySourceNotFoundException extends RuntimeException { + + ZookeeperPropertySourceNotFoundException(Exception source) { + super(source); + } + } +} diff --git a/spring-cloud-zookeeper-config/src/test/java/org/springframework/cloud/zookeeper/config/ZookeeperConfigDataLocationResolverTests.java b/spring-cloud-zookeeper-config/src/test/java/org/springframework/cloud/zookeeper/config/ZookeeperConfigDataLocationResolverTests.java index 2704f9f9..5c6c741d 100644 --- a/spring-cloud-zookeeper-config/src/test/java/org/springframework/cloud/zookeeper/config/ZookeeperConfigDataLocationResolverTests.java +++ b/spring-cloud-zookeeper-config/src/test/java/org/springframework/cloud/zookeeper/config/ZookeeperConfigDataLocationResolverTests.java @@ -20,6 +20,7 @@ import java.util.Collections; import java.util.List; import java.util.stream.Collectors; +import org.apache.commons.logging.LogFactory; import org.junit.jupiter.api.Test; import org.springframework.boot.ConfigurableBootstrapContext; @@ -39,7 +40,7 @@ public class ZookeeperConfigDataLocationResolverTests { @Test public void testParseLocation() { - ZookeeperConfigDataLocationResolver resolver = new ZookeeperConfigDataLocationResolver(); + ZookeeperConfigDataLocationResolver resolver = new ZookeeperConfigDataLocationResolver(LogFactory.getLog(getClass())); UriComponents uriComponents = resolver.parseLocation( "zookeeper:myhost:2182/mypath1;/mypath2;/mypath3"); assertThat(uriComponents.toUri()).hasScheme("zookeeper").hasHost("myhost") @@ -102,7 +103,7 @@ public class ZookeeperConfigDataLocationResolverTests { } private ZookeeperConfigDataLocationResolver createResolver() { - return new ZookeeperConfigDataLocationResolver(); + return new ZookeeperConfigDataLocationResolver(LogFactory.getLog(getClass())); } } diff --git a/spring-cloud-zookeeper-config/src/test/java/org/springframework/cloud/zookeeper/config/ZookeeperPropertySourceLocatorNoApplicationNameTests.java b/spring-cloud-zookeeper-config/src/test/java/org/springframework/cloud/zookeeper/config/ZookeeperPropertySourceLocatorNoApplicationNameTests.java index 77e1ebd5..2e3bb108 100644 --- a/spring-cloud-zookeeper-config/src/test/java/org/springframework/cloud/zookeeper/config/ZookeeperPropertySourceLocatorNoApplicationNameTests.java +++ b/spring-cloud-zookeeper-config/src/test/java/org/springframework/cloud/zookeeper/config/ZookeeperPropertySourceLocatorNoApplicationNameTests.java @@ -34,8 +34,10 @@ public class ZookeeperPropertySourceLocatorNoApplicationNameTests { public void defaultSpringApplicationNameWorks() { CuratorFramework curator = mock(CuratorFramework.class); when(curator.getChildren()).thenReturn(mock(GetChildrenBuilder.class)); + ZookeeperConfigProperties properties = new ZookeeperConfigProperties(); + properties.setName("notempty"); ZookeeperPropertySourceLocator locator = new ZookeeperPropertySourceLocator( - curator, new ZookeeperConfigProperties()); + curator, properties); locator.locate(new MockEnvironment()); }