2626import java .util .LinkedHashSet ;
2727import java .util .List ;
2828import java .util .Set ;
29- import java .util .function .Supplier ;
29+ import java .util .function .Function ;
3030
31+ import org .springframework .boot .context .properties .bind .BindResult ;
3132import org .springframework .boot .context .properties .bind .Bindable ;
3233import org .springframework .boot .context .properties .bind .Binder ;
3334import org .springframework .boot .context .properties .source .ConfigurationPropertyName ;
@@ -61,9 +62,7 @@ public class Profiles implements Iterable<String> {
6162 private static final Bindable <MultiValueMap <String , String >> STRING_STRINGS_MAP = Bindable
6263 .of (ResolvableType .forClassWithGenerics (MultiValueMap .class , String .class , String .class ));
6364
64- private static final Set <String > UNSET_ACTIVE = Collections .emptySet ();
65-
66- private static final Set <String > UNSET_DEFAULT = Collections .singleton ("default" );
65+ private static final Bindable <Set <String >> STRING_SET = Bindable .setOf (String .class );
6766
6867 private final MultiValueMap <String , String > groups ;
6968
@@ -86,32 +85,42 @@ public class Profiles implements Iterable<String> {
8685
8786 private List <String > getActivatedProfiles (Environment environment , Binder binder ,
8887 Collection <String > additionalProfiles ) {
89- return asUniqueItemList (get (environment , binder , environment ::getActiveProfiles ,
90- AbstractEnvironment .ACTIVE_PROFILES_PROPERTY_NAME , UNSET_ACTIVE ), additionalProfiles );
88+ return asUniqueItemList (getProfiles (environment , binder , Type .ACTIVE ), additionalProfiles );
9189 }
9290
9391 private List <String > getDefaultProfiles (Environment environment , Binder binder ) {
94- return asUniqueItemList (get (environment , binder , environment ::getDefaultProfiles ,
95- AbstractEnvironment .DEFAULT_PROFILES_PROPERTY_NAME , UNSET_DEFAULT ));
92+ return asUniqueItemList (getProfiles (environment , binder , Type .DEFAULT ));
9693 }
9794
98- private String [] get (Environment environment , Binder binder , Supplier <String []> supplier , String propertyName ,
99- Set <String > unset ) {
100- String propertyValue = environment .getProperty (propertyName );
101- if (hasExplicit (supplier , propertyValue , unset )) {
102- return supplier .get ();
95+ private Collection <String > getProfiles (Environment environment , Binder binder , Type type ) {
96+ String environmentPropertyValue = environment .getProperty (type .getName ());
97+ Set <String > environmentPropertyProfiles = (!StringUtils .hasLength (environmentPropertyValue ))
98+ ? Collections .emptySet ()
99+ : StringUtils .commaDelimitedListToSet (StringUtils .trimAllWhitespace (environmentPropertyValue ));
100+ Set <String > environmentProfiles = new LinkedHashSet <>(Arrays .asList (type .get (environment )));
101+ BindResult <Set <String >> boundProfiles = binder .bind (type .getName (), STRING_SET );
102+ if (hasProgrammaticallySetProfiles (type , environmentPropertyValue , environmentPropertyProfiles ,
103+ environmentProfiles )) {
104+ if (!type .isMergeWithEnvironmentProfiles () || !boundProfiles .isBound ()) {
105+ return environmentProfiles ;
106+ }
107+ return boundProfiles .map ((bound ) -> merge (environmentProfiles , bound )).get ();
103108 }
104- return binder . bind ( propertyName , String []. class ). orElseGet (() -> StringUtils . toStringArray ( unset ));
109+ return boundProfiles . orElse ( type . getDefaultValue ( ));
105110 }
106111
107- private boolean hasExplicit ( Supplier < String []> supplier , String propertyValue , Set < String > unset ) {
108- Set <String > profiles = new LinkedHashSet <>( Arrays . asList ( supplier . get ()));
109- if (!StringUtils .hasLength (propertyValue )) {
110- return !unset . equals (profiles );
112+ private boolean hasProgrammaticallySetProfiles ( Type type , String environmentPropertyValue ,
113+ Set <String > environmentPropertyProfiles , Set < String > environmentProfiles ) {
114+ if (!StringUtils .hasLength (environmentPropertyValue )) {
115+ return !type . getDefaultValue (). equals (environmentProfiles );
111116 }
112- Set <String > propertyProfiles = StringUtils
113- .commaDelimitedListToSet (StringUtils .trimAllWhitespace (propertyValue ));
114- return !propertyProfiles .equals (profiles );
117+ return !environmentPropertyProfiles .equals (environmentProfiles );
118+ }
119+
120+ private Set <String > merge (Set <String > environmentProfiles , Set <String > bound ) {
121+ Set <String > result = new LinkedHashSet <>(environmentProfiles );
122+ result .addAll (bound );
123+ return result ;
115124 }
116125
117126 private List <String > expandProfiles (List <String > profiles ) {
@@ -124,7 +133,7 @@ private List<String> expandProfiles(List<String> profiles) {
124133 asReversedList (this .groups .get (current )).forEach (stack ::push );
125134 }
126135 }
127- return asUniqueItemList (StringUtils . toStringArray ( expandedProfiles ) );
136+ return asUniqueItemList (expandedProfiles );
128137 }
129138
130139 private List <String > asReversedList (List <String > list ) {
@@ -136,12 +145,12 @@ private List<String> asReversedList(List<String> list) {
136145 return reversed ;
137146 }
138147
139- private List <String > asUniqueItemList (String [] array ) {
140- return asUniqueItemList (array , null );
148+ private List <String > asUniqueItemList (Collection < String > strings ) {
149+ return asUniqueItemList (strings , null );
141150 }
142151
143- private List <String > asUniqueItemList (String [] array , Collection <String > additional ) {
144- LinkedHashSet <String > uniqueItems = new LinkedHashSet <>(Arrays . asList ( array ) );
152+ private List <String > asUniqueItemList (Collection < String > strings , Collection <String > additional ) {
153+ LinkedHashSet <String > uniqueItems = new LinkedHashSet <>(strings );
145154 if (!CollectionUtils .isEmpty (additional )) {
146155 uniqueItems .addAll (additional );
147156 }
@@ -198,4 +207,49 @@ public String toString() {
198207 return creator .toString ();
199208 }
200209
210+ /**
211+ * A profiles type that can be obtained.
212+ */
213+ private enum Type {
214+
215+ ACTIVE (AbstractEnvironment .ACTIVE_PROFILES_PROPERTY_NAME , Environment ::getActiveProfiles , true ,
216+ Collections .emptySet ()),
217+
218+ DEFAULT (AbstractEnvironment .DEFAULT_PROFILES_PROPERTY_NAME , Environment ::getDefaultProfiles , false ,
219+ Collections .singleton ("default" ));
220+
221+ private final Function <Environment , String []> getter ;
222+
223+ private final boolean mergeWithEnvironmentProfiles ;
224+
225+ private final String name ;
226+
227+ private final Set <String > defaultValue ;
228+
229+ Type (String name , Function <Environment , String []> getter , boolean mergeWithEnvironmentProfiles ,
230+ Set <String > defaultValue ) {
231+ this .name = name ;
232+ this .getter = getter ;
233+ this .mergeWithEnvironmentProfiles = mergeWithEnvironmentProfiles ;
234+ this .defaultValue = defaultValue ;
235+ }
236+
237+ String getName () {
238+ return this .name ;
239+ }
240+
241+ String [] get (Environment environment ) {
242+ return this .getter .apply (environment );
243+ }
244+
245+ Set <String > getDefaultValue () {
246+ return this .defaultValue ;
247+ }
248+
249+ boolean isMergeWithEnvironmentProfiles () {
250+ return this .mergeWithEnvironmentProfiles ;
251+ }
252+
253+ }
254+
201255}
0 commit comments