@ -1,5 +1,5 @@
/ *
/ *
* Copyright 2012 - 20 19 the original author or authors .
* Copyright 2012 - 20 20 the original author or authors .
*
*
* Licensed under the Apache License , Version 2.0 ( the "License" ) ;
* Licensed under the Apache License , Version 2.0 ( the "License" ) ;
* you may not use this file except in compliance with the License .
* you may not use this file except in compliance with the License .
@ -62,6 +62,7 @@ import org.springframework.core.env.PropertySource;
import org.springframework.core.io.DefaultResourceLoader ;
import org.springframework.core.io.DefaultResourceLoader ;
import org.springframework.core.io.Resource ;
import org.springframework.core.io.Resource ;
import org.springframework.core.io.ResourceLoader ;
import org.springframework.core.io.ResourceLoader ;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver ;
import org.springframework.core.io.support.SpringFactoriesLoader ;
import org.springframework.core.io.support.SpringFactoriesLoader ;
import org.springframework.util.Assert ;
import org.springframework.util.Assert ;
import org.springframework.util.CollectionUtils ;
import org.springframework.util.CollectionUtils ;
@ -75,6 +76,7 @@ import org.springframework.util.StringUtils;
* ' application . properties ' and / or ' application . yml ' files in the following locations :
* ' application . properties ' and / or ' application . yml ' files in the following locations :
* < ul >
* < ul >
* < li > file : . / config / < / li >
* < li > file : . / config / < / li >
* < li > file : . / config / { @literal * } / < / li >
* < li > file : . / < / li >
* < li > file : . / < / li >
* < li > classpath : config / < / li >
* < li > classpath : config / < / li >
* < li > classpath : < / li >
* < li > classpath : < / li >
@ -107,7 +109,7 @@ public class ConfigFileApplicationListener implements EnvironmentPostProcessor,
private static final String DEFAULT_PROPERTIES = "defaultProperties" ;
private static final String DEFAULT_PROPERTIES = "defaultProperties" ;
// Note the order is from least to most specific (last one wins)
// Note the order is from least to most specific (last one wins)
private static final String DEFAULT_SEARCH_LOCATIONS = "classpath:/,classpath:/config/,file:./,file:./config/ ";
private static final String DEFAULT_SEARCH_LOCATIONS = "classpath:/,classpath:/config/,file:./,file:./config/ */,file:./config/ ";
private static final String DEFAULT_NAMES = "application" ;
private static final String DEFAULT_NAMES = "application" ;
@ -158,6 +160,8 @@ public class ConfigFileApplicationListener implements EnvironmentPostProcessor,
private final DeferredLog logger = new DeferredLog ( ) ;
private final DeferredLog logger = new DeferredLog ( ) ;
private static final Resource [ ] EMPTY_RESOURCES = { } ;
private String searchLocations ;
private String searchLocations ;
private String names ;
private String names ;
@ -299,6 +303,8 @@ public class ConfigFileApplicationListener implements EnvironmentPostProcessor,
private final ResourceLoader resourceLoader ;
private final ResourceLoader resourceLoader ;
private final PathMatchingResourcePatternResolver patternResolver ;
private final List < PropertySourceLoader > propertySourceLoaders ;
private final List < PropertySourceLoader > propertySourceLoaders ;
private Deque < Profile > profiles ;
private Deque < Profile > profiles ;
@ -317,6 +323,7 @@ public class ConfigFileApplicationListener implements EnvironmentPostProcessor,
this . resourceLoader = ( resourceLoader ! = null ) ? resourceLoader : new DefaultResourceLoader ( ) ;
this . resourceLoader = ( resourceLoader ! = null ) ? resourceLoader : new DefaultResourceLoader ( ) ;
this . propertySourceLoaders = SpringFactoriesLoader . loadFactories ( PropertySourceLoader . class ,
this . propertySourceLoaders = SpringFactoriesLoader . loadFactories ( PropertySourceLoader . class ,
getClass ( ) . getClassLoader ( ) ) ;
getClass ( ) . getClassLoader ( ) ) ;
this . patternResolver = new PathMatchingResourcePatternResolver ( this . resourceLoader ) ;
}
}
void load ( ) {
void load ( ) {
@ -497,47 +504,51 @@ public class ConfigFileApplicationListener implements EnvironmentPostProcessor,
private void load ( PropertySourceLoader loader , String location , Profile profile , DocumentFilter filter ,
private void load ( PropertySourceLoader loader , String location , Profile profile , DocumentFilter filter ,
DocumentConsumer consumer ) {
DocumentConsumer consumer ) {
try {
try {
Resource resource = this . resourceLoader . getResource ( location ) ;
Resource [ ] resources = getResources ( location ) ;
if ( resource = = null | | ! resource . exists ( ) ) {
for ( Resource resource : resources ) {
if ( this . logger . isTraceEnabled ( ) ) {
if ( resource = = null | | ! resource . exists ( ) ) {
StringBuilder description = getDescription ( "Skipped missing config " , location , resource ,
if ( this . logger . isTraceEnabled ( ) ) {
profile ) ;
StringBuilder description = getDescription ( "Skipped missing config " , location , resource ,
this . logger . trace ( description ) ;
profile ) ;
this . logger . trace ( description ) ;
}
return ;
}
}
return ;
if ( ! StringUtils . hasText ( StringUtils . getFilenameExtension ( resource . getFilename ( ) ) ) ) {
}
if ( this . logger . isTraceEnabled ( ) ) {
if ( ! StringUtils . hasText ( StringUtils . getFilenameExtension ( resource . getFilename ( ) ) ) ) {
StringBuilder description = getDescription ( "Skipped empty config extension " , location ,
if ( this . logger . isTraceEnabled ( ) ) {
resource , profile ) ;
StringBuilder description = getDescription ( "Skipped empty config extension " , location ,
this . logger . trace ( description ) ;
resource , profile ) ;
}
this. logger . trace ( description ) ;
return ;
}
}
return ;
String name = ( location . contains ( "*" ) ) ? "applicationConfig: [" + resource . toString ( ) + "]"
}
: "applicationConfig: [" + location + "]" ;
String name = "applicationConfig: [" + location + "]" ;
List < Document > documents = loadDocuments ( loader , name , resource ) ;
List < Document > documents = loadDocuments ( loader , name , resource ) ;
if ( CollectionUtils . isEmpty ( documents ) ) {
if ( CollectionUtils . isEmpty ( documents ) ) {
if ( this . logger . isTraceEnabled ( ) ) {
if ( this . logger . isTraceEnabled ( ) ) {
StringBuilder description = getDescription ( "Skipped unloaded config " , location , resource ,
StringBuilder description = getDescription ( "Skipped unloaded config " , location , resource ,
profile ) ;
profile ) ;
this . logger . trace ( description ) ;
this . logger . trace ( description ) ;
}
return ;
}
}
return ;
List < Document > loaded = new ArrayList < > ( ) ;
}
for ( Document document : documents ) {
List < Document > loaded = new ArrayList < > ( ) ;
if ( filter . match ( document ) ) {
for ( Document document : documents ) {
addActiveProfiles ( document . getActiveProfiles ( ) ) ;
if ( filter . match ( document ) ) {
addIncludedProfiles ( document . getIncludeProfiles ( ) ) ;
addActiveProfiles ( document . getActiveProfiles ( ) ) ;
loaded . add ( document ) ;
addIncludedProfiles ( document . getIncludeProfiles ( ) ) ;
}
loaded . add ( document ) ;
}
}
}
Collections . reverse ( loaded ) ;
Collections . reverse ( loaded ) ;
if ( ! loaded . isEmpty ( ) ) {
if ( ! loaded . isEmpty ( ) ) {
loaded . forEach ( ( document ) - > consumer . accept ( profile , document ) ) ;
loaded . forEach ( ( document ) - > consumer . accept ( profile , document ) ) ;
if ( this . logger . isDebugEnabled ( ) ) {
if ( this . logger . isDebugEnabled ( ) ) {
StringBuilder description = getDescription ( "Loaded config file " , location , resource ,
StringBuilder description = getDescription ( "Loaded config file " , location , resource , profile ) ;
profile ) ;
this . logger . debug ( description ) ;
this . logger . debug ( description ) ;
}
}
}
}
}
}
}
@ -546,6 +557,15 @@ public class ConfigFileApplicationListener implements EnvironmentPostProcessor,
}
}
}
}
private Resource [ ] getResources ( String location ) {
try {
return this . patternResolver . getResources ( location ) ;
}
catch ( IOException ex ) {
return EMPTY_RESOURCES ;
}
}
private void addIncludedProfiles ( Set < Profile > includeProfiles ) {
private void addIncludedProfiles ( Set < Profile > includeProfiles ) {
LinkedList < Profile > existingProfiles = new LinkedList < > ( this . profiles ) ;
LinkedList < Profile > existingProfiles = new LinkedList < > ( this . profiles ) ;
this . profiles . clear ( ) ;
this . profiles . clear ( ) ;