From 3a887151e6f9f67062ed8f2a7d3f593a1ee2cff9 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Wed, 31 Aug 2016 16:08:43 +0100 Subject: [PATCH] Remove use of regular expressions in Spring profile-based doc matching Closes gh-1309 --- .../boot/yaml/ArrayDocumentMatcher.java | 2 + .../yaml/SpringProfileDocumentMatcher.java | 84 +++++++++++++++++-- .../boot/yaml/ArrayDocumentMatcherTests.java | 1 + 3 files changed, 80 insertions(+), 7 deletions(-) diff --git a/spring-boot/src/main/java/org/springframework/boot/yaml/ArrayDocumentMatcher.java b/spring-boot/src/main/java/org/springframework/boot/yaml/ArrayDocumentMatcher.java index fc92743c16..13344e2221 100644 --- a/spring-boot/src/main/java/org/springframework/boot/yaml/ArrayDocumentMatcher.java +++ b/spring-boot/src/main/java/org/springframework/boot/yaml/ArrayDocumentMatcher.java @@ -30,7 +30,9 @@ import org.springframework.util.StringUtils; * values (interpreted as regexes). * * @author Dave Syer + * @deprecated as of 1.4.1 in favor of exact String-based matching */ +@Deprecated public class ArrayDocumentMatcher implements DocumentMatcher { private final String key; diff --git a/spring-boot/src/main/java/org/springframework/boot/yaml/SpringProfileDocumentMatcher.java b/spring-boot/src/main/java/org/springframework/boot/yaml/SpringProfileDocumentMatcher.java index e1b5e1db34..8e0fec294e 100644 --- a/spring-boot/src/main/java/org/springframework/boot/yaml/SpringProfileDocumentMatcher.java +++ b/spring-boot/src/main/java/org/springframework/boot/yaml/SpringProfileDocumentMatcher.java @@ -18,8 +18,10 @@ package org.springframework.boot.yaml; import java.util.Arrays; import java.util.Collections; +import java.util.HashSet; import java.util.LinkedHashSet; import java.util.Properties; +import java.util.Set; import org.springframework.beans.factory.config.YamlProcessor.DocumentMatcher; import org.springframework.beans.factory.config.YamlProcessor.MatchStatus; @@ -39,8 +41,6 @@ import org.springframework.util.StringUtils; */ public class SpringProfileDocumentMatcher implements DocumentMatcher { - private static final String[] DEFAULT_PROFILES = new String[] { "^\\s*$" }; - private static final String SPRING_PROFILES = "spring.profiles"; private String[] activeProfiles = new String[0]; @@ -80,11 +80,9 @@ public class SpringProfileDocumentMatcher implements DocumentMatcher { } private DocumentMatcher getActiveProfilesDocumentMatcher() { - String[] profiles = this.activeProfiles; - if (profiles.length == 0) { - profiles = DEFAULT_PROFILES; - } - return new ArrayDocumentMatcher(SPRING_PROFILES, profiles); + return this.activeProfiles.length == 0 ? new EmptyProfileDocumentMatcher() + : new ActiveProfilesDocumentMatcher( + new HashSet(Arrays.asList(this.activeProfiles))); } private String extractProfiles(String profiles, ProfileType type) { @@ -112,4 +110,76 @@ public class SpringProfileDocumentMatcher implements DocumentMatcher { POSITIVE, NEGATIVE } + /** + * Base class for profile-based {@link DocumentMatcher DocumentMatchers}. + */ + private static abstract class AbstractProfileDocumentMatcher + implements DocumentMatcher { + + @Override + public final MatchStatus matches(Properties properties) { + if (!properties.containsKey(SPRING_PROFILES)) { + return MatchStatus.ABSTAIN; + } + Set profiles = StringUtils + .commaDelimitedListToSet(properties.getProperty(SPRING_PROFILES)); + return matches(profiles); + } + + protected abstract MatchStatus matches(Set profiles); + + } + + /** + * {@link AbstractProfileDocumentMatcher} that matches a document when a value in + * {@code spring.profiles} is also in {@code spring.profiles.active}. + */ + private static class ActiveProfilesDocumentMatcher + extends AbstractProfileDocumentMatcher { + + private final Set activeProfiles; + + ActiveProfilesDocumentMatcher(Set activeProfiles) { + this.activeProfiles = activeProfiles; + } + + @Override + protected MatchStatus matches(Set profiles) { + if (profiles.isEmpty()) { + return MatchStatus.NOT_FOUND; + } + for (String activeProfile : this.activeProfiles) { + if (profiles.contains(activeProfile)) { + return MatchStatus.FOUND; + } + } + return MatchStatus.NOT_FOUND; + } + + } + + /** + * {@link AbstractProfileDocumentMatcher} that matches a document when {@code + * spring.profiles} is empty or contains a value with no text. + * + * @see StringUtils#hasText(String) + */ + private static class EmptyProfileDocumentMatcher + extends AbstractProfileDocumentMatcher { + + @Override + public MatchStatus matches(Set profiles) { + if (profiles.isEmpty()) { + return MatchStatus.FOUND; + } + for (String profile : profiles) { + if (!StringUtils.hasText(profile)) { + return MatchStatus.FOUND; + } + } + return MatchStatus.NOT_FOUND; + } + + } + } diff --git a/spring-boot/src/test/java/org/springframework/boot/yaml/ArrayDocumentMatcherTests.java b/spring-boot/src/test/java/org/springframework/boot/yaml/ArrayDocumentMatcherTests.java index 2f5ff5dba8..52da06a31f 100644 --- a/spring-boot/src/test/java/org/springframework/boot/yaml/ArrayDocumentMatcherTests.java +++ b/spring-boot/src/test/java/org/springframework/boot/yaml/ArrayDocumentMatcherTests.java @@ -32,6 +32,7 @@ import static org.assertj.core.api.Assertions.assertThat; * * @author Dave Syer */ +@Deprecated public class ArrayDocumentMatcherTests { @Test