|
|
|
|
@ -17,6 +17,8 @@
@@ -17,6 +17,8 @@
|
|
|
|
|
package org.springframework.boot.autoconfigure; |
|
|
|
|
|
|
|
|
|
import java.io.IOException; |
|
|
|
|
import java.util.Iterator; |
|
|
|
|
import java.util.Set; |
|
|
|
|
|
|
|
|
|
import org.springframework.boot.autoconfigure.MessageSourceAutoConfiguration.ResourceBundleCondition; |
|
|
|
|
import org.springframework.boot.autoconfigure.condition.ConditionOutcome; |
|
|
|
|
@ -35,6 +37,7 @@ import org.springframework.core.annotation.Order;
@@ -35,6 +37,7 @@ import org.springframework.core.annotation.Order;
|
|
|
|
|
import org.springframework.core.io.Resource; |
|
|
|
|
import org.springframework.core.io.support.PathMatchingResourcePatternResolver; |
|
|
|
|
import org.springframework.core.type.AnnotatedTypeMetadata; |
|
|
|
|
import org.springframework.util.ConcurrentReferenceHashMap; |
|
|
|
|
import org.springframework.util.StringUtils; |
|
|
|
|
|
|
|
|
|
import static org.springframework.util.StringUtils.commaDelimitedListToStringArray; |
|
|
|
|
@ -44,6 +47,7 @@ import static org.springframework.util.StringUtils.trimAllWhitespace;
@@ -44,6 +47,7 @@ import static org.springframework.util.StringUtils.trimAllWhitespace;
|
|
|
|
|
* {@link EnableAutoConfiguration Auto-configuration} for {@link MessageSource}. |
|
|
|
|
* |
|
|
|
|
* @author Dave Syer |
|
|
|
|
* @author Phillip Webb |
|
|
|
|
*/ |
|
|
|
|
@Configuration |
|
|
|
|
@ConditionalOnMissingBean(MessageSource.class) |
|
|
|
|
@ -99,11 +103,23 @@ public class MessageSourceAutoConfiguration {
@@ -99,11 +103,23 @@ public class MessageSourceAutoConfiguration {
|
|
|
|
|
|
|
|
|
|
protected static class ResourceBundleCondition extends SpringBootCondition { |
|
|
|
|
|
|
|
|
|
private static ConcurrentReferenceHashMap<String, ConditionOutcome> cache = new ConcurrentReferenceHashMap<String, ConditionOutcome>(); |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
public ConditionOutcome getMatchOutcome(ConditionContext context, |
|
|
|
|
AnnotatedTypeMetadata metadata) { |
|
|
|
|
String basename = context.getEnvironment().getProperty( |
|
|
|
|
"spring.messages.basename", "messages"); |
|
|
|
|
ConditionOutcome outcome = cache.get(basename); |
|
|
|
|
if (outcome == null) { |
|
|
|
|
outcome = getMatchOutcomeForBasename(context, basename); |
|
|
|
|
cache.put(basename, outcome); |
|
|
|
|
} |
|
|
|
|
return outcome; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private ConditionOutcome getMatchOutcomeForBasename(ConditionContext context, |
|
|
|
|
String basename) { |
|
|
|
|
for (String name : commaDelimitedListToStringArray(trimAllWhitespace(basename))) { |
|
|
|
|
for (Resource resource : getResources(context.getClassLoader(), name)) { |
|
|
|
|
if (resource.exists()) { |
|
|
|
|
@ -118,7 +134,7 @@ public class MessageSourceAutoConfiguration {
@@ -118,7 +134,7 @@ public class MessageSourceAutoConfiguration {
|
|
|
|
|
|
|
|
|
|
private Resource[] getResources(ClassLoader classLoader, String name) { |
|
|
|
|
try { |
|
|
|
|
return new PathMatchingResourcePatternResolver(classLoader) |
|
|
|
|
return new SkipPatternPathMatchingResourcePatternResolver(classLoader) |
|
|
|
|
.getResources("classpath*:" + name + "*.properties"); |
|
|
|
|
} |
|
|
|
|
catch (IOException ex) { |
|
|
|
|
@ -128,4 +144,60 @@ public class MessageSourceAutoConfiguration {
@@ -128,4 +144,60 @@ public class MessageSourceAutoConfiguration {
|
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* {@link PathMatchingResourcePatternResolver} that skips well known JARs that don't |
|
|
|
|
* contain messages.properties. |
|
|
|
|
*/ |
|
|
|
|
private static class SkipPatternPathMatchingResourcePatternResolver extends |
|
|
|
|
PathMatchingResourcePatternResolver { |
|
|
|
|
|
|
|
|
|
private static final ClassLoader ROOT_CLASSLOADER; |
|
|
|
|
static { |
|
|
|
|
ClassLoader classLoader = ClassLoader.getSystemClassLoader(); |
|
|
|
|
while (classLoader.getParent() != null) { |
|
|
|
|
classLoader = classLoader.getParent(); |
|
|
|
|
} |
|
|
|
|
ROOT_CLASSLOADER = classLoader; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
private static final String[] SKIPPED = { "aspectjweaver-", "hibernate-core-", |
|
|
|
|
"hsqldb-", "jackson-annotations-", "jackson-core-", "jackson-databind-", |
|
|
|
|
"javassist-", "snakeyaml-", "spring-aop-", "spring-beans-", |
|
|
|
|
"spring-boot-", "spring-boot-actuator-", "spring-boot-autoconfigure-", |
|
|
|
|
"spring-core-", "spring-context-", "spring-data-commons-", |
|
|
|
|
"spring-expression-", "spring-jdbc-", "spring-orm-", "spring-tx-", |
|
|
|
|
"spring-web-", "spring-webmvc-", "tomcat-embed-", "joda-time-", |
|
|
|
|
"hibernate-entitymanager-", "hibernate-validator-", "logback-classic-", |
|
|
|
|
"logback-core-", "thymeleaf-" }; |
|
|
|
|
|
|
|
|
|
public SkipPatternPathMatchingResourcePatternResolver(ClassLoader classLoader) { |
|
|
|
|
super(classLoader); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
protected void addAllClassLoaderJarRoots(ClassLoader classLoader, |
|
|
|
|
Set<Resource> result) { |
|
|
|
|
if (classLoader != ROOT_CLASSLOADER) { |
|
|
|
|
super.addAllClassLoaderJarRoots(classLoader, result); |
|
|
|
|
} |
|
|
|
|
}; |
|
|
|
|
|
|
|
|
|
@Override |
|
|
|
|
protected Set<Resource> doFindAllClassPathResources(String path) |
|
|
|
|
throws IOException { |
|
|
|
|
Set<Resource> resources = super.doFindAllClassPathResources(path); |
|
|
|
|
for (Iterator<Resource> iterator = resources.iterator(); iterator.hasNext();) { |
|
|
|
|
Resource resource = iterator.next(); |
|
|
|
|
for (String skipped : SKIPPED) { |
|
|
|
|
if (resource.getFilename().startsWith(skipped)) { |
|
|
|
|
iterator.remove(); |
|
|
|
|
break; |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
return resources; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|
|