Skip to content

Commit 952045c

Browse files
aleskiewiczjhoeller
authored andcommitted
SPR-17606 @Profile mishandles "not" operand mixed with "&" (#2066)
Correct handling of not/and expressions in ProfilesParser Issue: SPR-17606
1 parent 815f151 commit 952045c

File tree

2 files changed

+72
-5
lines changed

2 files changed

+72
-5
lines changed

spring-core/src/main/java/org/springframework/core/env/ProfilesParser.java

Lines changed: 21 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -54,6 +54,9 @@ private static Profiles parseExpression(String expression) {
5454
}
5555

5656
private static Profiles parseTokens(String expression, StringTokenizer tokens) {
57+
return parseTokens(expression, tokens, Context.NONE);
58+
}
59+
private static Profiles parseTokens(String expression, StringTokenizer tokens, Context context) {
5760
List<Profiles> elements = new ArrayList<>();
5861
Operator operator = null;
5962
while (tokens.hasMoreTokens()) {
@@ -63,7 +66,11 @@ private static Profiles parseTokens(String expression, StringTokenizer tokens) {
6366
}
6467
switch (token) {
6568
case "(":
66-
elements.add(parseTokens(expression, tokens));
69+
Profiles contents = parseTokens(expression, tokens, Context.BRACKET);
70+
if (context == Context.INVERT) {
71+
return contents;
72+
}
73+
elements.add(contents);
6774
break;
6875
case "&":
6976
assertWellFormed(expression, operator == null || operator == Operator.AND);
@@ -74,16 +81,23 @@ private static Profiles parseTokens(String expression, StringTokenizer tokens) {
7481
operator = Operator.OR;
7582
break;
7683
case "!":
77-
elements.add(not(parseTokens(expression, tokens)));
84+
elements.add(not(parseTokens(expression, tokens, Context.INVERT)));
7885
break;
7986
case ")":
8087
Profiles merged = merge(expression, elements, operator);
88+
if (context == Context.BRACKET) {
89+
return merged;
90+
}
8191
elements.clear();
8292
elements.add(merged);
8393
operator = null;
8494
break;
8595
default:
86-
elements.add(equals(token));
96+
Profiles value = equals(token);
97+
if (context == Context.INVERT) {
98+
return value;
99+
}
100+
elements.add(value);
87101
}
88102
}
89103
return merge(expression, elements, operator);
@@ -126,6 +140,9 @@ private static Predicate<Profiles> isMatch(Predicate<String> activeProfile) {
126140
private enum Operator {AND, OR}
127141

128142

143+
private enum Context {NONE, INVERT, BRACKET}
144+
145+
129146
private static class ParsedProfiles implements Profiles {
130147

131148
private final String[] expressions;

spring-core/src/test/java/org/springframework/core/env/ProfilesTests.java

Lines changed: 51 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2018 the original author or authors.
2+
* Copyright 2002-2019 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -195,6 +195,56 @@ private void assertOfNotAndExpression(Profiles profiles) {
195195
assertTrue(profiles.matches(activeProfiles("java")));
196196
}
197197

198+
@Test
199+
public void ofAndExpressionWithInvertedSingleElement() {
200+
Profiles profiles = Profiles.of("!spring & framework");
201+
assertOfAndExpressionWithInvertedSingleElement(profiles);
202+
}
203+
204+
@Test
205+
public void ofAndExpressionWithInBracketsInvertedSingleElement() {
206+
Profiles profiles = Profiles.of("(!spring) & framework");
207+
assertOfAndExpressionWithInvertedSingleElement(profiles);
208+
}
209+
210+
@Test
211+
public void ofAndExpressionWithInvertedSingleElementInBrackets() {
212+
Profiles profiles = Profiles.of("! (spring) & framework");
213+
assertOfAndExpressionWithInvertedSingleElement(profiles);
214+
}
215+
216+
@Test
217+
public void ofAndExpressionWithInvertedSingleElementInBracketsWithoutSpaces() {
218+
Profiles profiles = Profiles.of("!(spring)&framework");
219+
assertOfAndExpressionWithInvertedSingleElement(profiles);
220+
}
221+
222+
@Test
223+
public void ofAndExpressionWithInvertedSingleElementWithoutSpaces() {
224+
Profiles profiles = Profiles.of("!spring&framework");
225+
assertOfAndExpressionWithInvertedSingleElement(profiles);
226+
}
227+
228+
private void assertOfAndExpressionWithInvertedSingleElement(Profiles profiles) {
229+
assertTrue(profiles.matches(activeProfiles("framework")));
230+
assertFalse(profiles.matches(activeProfiles("java")));
231+
assertFalse(profiles.matches(activeProfiles("spring", "framework")));
232+
assertFalse(profiles.matches(activeProfiles("spring")));
233+
}
234+
235+
@Test
236+
public void ofOrExpressionWithInvertedSingleElementWithoutSpaces() {
237+
Profiles profiles = Profiles.of("!spring|framework");
238+
assertOfOrExpressionWithInvertedSingleElement(profiles);
239+
}
240+
241+
private void assertOfOrExpressionWithInvertedSingleElement(Profiles profiles) {
242+
assertTrue(profiles.matches(activeProfiles("framework")));
243+
assertTrue(profiles.matches(activeProfiles("java")));
244+
assertTrue(profiles.matches(activeProfiles("spring", "framework")));
245+
assertFalse(profiles.matches(activeProfiles("spring")));
246+
}
247+
198248
@Test
199249
public void ofNotOrExpression() {
200250
Profiles profiles = Profiles.of("!(spring | framework)");

0 commit comments

Comments
 (0)