|
|
|
@ -1,5 +1,5 @@
@@ -1,5 +1,5 @@
|
|
|
|
|
/* |
|
|
|
|
* Copyright 2002-2015 the original author or authors. |
|
|
|
|
* Copyright 2002-2016 the original author or authors. |
|
|
|
|
* |
|
|
|
|
* Licensed under the Apache License, Version 2.0 (the "License"); |
|
|
|
|
* you may not use this file except in compliance with the License. |
|
|
|
@ -25,6 +25,7 @@ import org.apache.commons.logging.LogFactory;
@@ -25,6 +25,7 @@ import org.apache.commons.logging.LogFactory;
|
|
|
|
|
|
|
|
|
|
import org.springframework.beans.BeanUtils; |
|
|
|
|
import org.springframework.context.ApplicationContext; |
|
|
|
|
import org.springframework.context.ApplicationContextException; |
|
|
|
|
import org.springframework.context.ApplicationContextInitializer; |
|
|
|
|
import org.springframework.context.ConfigurableApplicationContext; |
|
|
|
|
import org.springframework.core.GenericTypeResolver; |
|
|
|
@ -86,8 +87,8 @@ public abstract class AbstractContextLoader implements SmartContextLoader {
@@ -86,8 +87,8 @@ public abstract class AbstractContextLoader implements SmartContextLoader {
|
|
|
|
|
*/ |
|
|
|
|
@Override |
|
|
|
|
public void processContextConfiguration(ContextConfigurationAttributes configAttributes) { |
|
|
|
|
String[] processedLocations = processLocations(configAttributes.getDeclaringClass(), |
|
|
|
|
configAttributes.getLocations()); |
|
|
|
|
String[] processedLocations = |
|
|
|
|
processLocations(configAttributes.getDeclaringClass(), configAttributes.getLocations()); |
|
|
|
|
configAttributes.setLocations(processedLocations); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -135,7 +136,9 @@ public abstract class AbstractContextLoader implements SmartContextLoader {
@@ -135,7 +136,9 @@ public abstract class AbstractContextLoader implements SmartContextLoader {
|
|
|
|
|
@SuppressWarnings("unchecked") |
|
|
|
|
private void invokeApplicationContextInitializers(ConfigurableApplicationContext context, |
|
|
|
|
MergedContextConfiguration mergedConfig) { |
|
|
|
|
Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> initializerClasses = mergedConfig.getContextInitializerClasses(); |
|
|
|
|
|
|
|
|
|
Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> initializerClasses = |
|
|
|
|
mergedConfig.getContextInitializerClasses(); |
|
|
|
|
if (initializerClasses.isEmpty()) { |
|
|
|
|
// no ApplicationContextInitializers have been declared -> nothing to do
|
|
|
|
|
return; |
|
|
|
@ -145,13 +148,15 @@ public abstract class AbstractContextLoader implements SmartContextLoader {
@@ -145,13 +148,15 @@ public abstract class AbstractContextLoader implements SmartContextLoader {
|
|
|
|
|
Class<?> contextClass = context.getClass(); |
|
|
|
|
|
|
|
|
|
for (Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>> initializerClass : initializerClasses) { |
|
|
|
|
Class<?> initializerContextClass = GenericTypeResolver.resolveTypeArgument(initializerClass, |
|
|
|
|
ApplicationContextInitializer.class); |
|
|
|
|
Assert.isAssignable(initializerContextClass, contextClass, String.format( |
|
|
|
|
"Could not add context initializer [%s] since its generic parameter [%s] " |
|
|
|
|
+ "is not assignable from the type of application context used by this " |
|
|
|
|
+ "context loader [%s]: ", initializerClass.getName(), initializerContextClass.getName(), |
|
|
|
|
contextClass.getName())); |
|
|
|
|
Class<?> initializerContextClass = |
|
|
|
|
GenericTypeResolver.resolveTypeArgument(initializerClass, ApplicationContextInitializer.class); |
|
|
|
|
if (initializerContextClass != null && !initializerContextClass.isInstance(context)) { |
|
|
|
|
throw new ApplicationContextException(String.format( |
|
|
|
|
"Could not apply context initializer [%s] since its generic parameter [%s] " + |
|
|
|
|
"is not assignable from the type of application context used by this " + |
|
|
|
|
"context loader: [%s]", initializerClass.getName(), initializerContextClass.getName(), |
|
|
|
|
contextClass.getName())); |
|
|
|
|
} |
|
|
|
|
initializerInstances.add((ApplicationContextInitializer<ConfigurableApplicationContext>) BeanUtils.instantiateClass(initializerClass)); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
@ -161,6 +166,7 @@ public abstract class AbstractContextLoader implements SmartContextLoader {
@@ -161,6 +166,7 @@ public abstract class AbstractContextLoader implements SmartContextLoader {
|
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
// --- ContextLoader -------------------------------------------------------
|
|
|
|
|
|
|
|
|
|
/** |
|
|
|
@ -171,7 +177,6 @@ public abstract class AbstractContextLoader implements SmartContextLoader {
@@ -171,7 +177,6 @@ public abstract class AbstractContextLoader implements SmartContextLoader {
|
|
|
|
|
* and the configured {@linkplain #getResourceSuffixes() resource suffixes}; |
|
|
|
|
* otherwise, the supplied {@code locations} will be |
|
|
|
|
* {@linkplain #modifyLocations modified} if necessary and returned. |
|
|
|
|
* |
|
|
|
|
* @param clazz the class with which the locations are associated: to be |
|
|
|
|
* used when generating default locations |
|
|
|
|
* @param locations the unmodified locations to use for loading the |
|
|
|
@ -186,30 +191,26 @@ public abstract class AbstractContextLoader implements SmartContextLoader {
@@ -186,30 +191,26 @@ public abstract class AbstractContextLoader implements SmartContextLoader {
|
|
|
|
|
*/ |
|
|
|
|
@Override |
|
|
|
|
public final String[] processLocations(Class<?> clazz, String... locations) { |
|
|
|
|
return (ObjectUtils.isEmpty(locations) && isGenerateDefaultLocations()) ? generateDefaultLocations(clazz) |
|
|
|
|
: modifyLocations(clazz, locations); |
|
|
|
|
return (ObjectUtils.isEmpty(locations) && isGenerateDefaultLocations()) ? |
|
|
|
|
generateDefaultLocations(clazz) : modifyLocations(clazz, locations); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Generate the default classpath resource locations array based on the |
|
|
|
|
* supplied class. |
|
|
|
|
* |
|
|
|
|
* <p>For example, if the supplied class is {@code com.example.MyTest}, |
|
|
|
|
* the generated locations will contain a single string with a value of |
|
|
|
|
* {@code "classpath:com/example/MyTest<suffix>"}, where {@code <suffix>} |
|
|
|
|
* is the value of the first configured |
|
|
|
|
* {@linkplain #getResourceSuffixes() resource suffix} for which the |
|
|
|
|
* generated location actually exists in the classpath. |
|
|
|
|
* |
|
|
|
|
* <p>As of Spring 3.1, the implementation of this method adheres to the |
|
|
|
|
* contract defined in the {@link SmartContextLoader} SPI. Specifically, |
|
|
|
|
* this method will <em>preemptively</em> verify that the generated default |
|
|
|
|
* location actually exists. If it does not exist, this method will log a |
|
|
|
|
* warning and return an empty array. |
|
|
|
|
* |
|
|
|
|
* <p>Subclasses can override this method to implement a different |
|
|
|
|
* <em>default location generation</em> strategy. |
|
|
|
|
* |
|
|
|
|
* @param clazz the class for which the default locations are to be generated |
|
|
|
|
* @return an array of default application context resource locations |
|
|
|
|
* @since 2.5 |
|
|
|
@ -224,23 +225,22 @@ public abstract class AbstractContextLoader implements SmartContextLoader {
@@ -224,23 +225,22 @@ public abstract class AbstractContextLoader implements SmartContextLoader {
|
|
|
|
|
String resourcePath = ClassUtils.convertClassNameToResourcePath(clazz.getName()) + suffix; |
|
|
|
|
String prefixedResourcePath = ResourceUtils.CLASSPATH_URL_PREFIX + resourcePath; |
|
|
|
|
ClassPathResource classPathResource = new ClassPathResource(resourcePath); |
|
|
|
|
|
|
|
|
|
if (classPathResource.exists()) { |
|
|
|
|
if (logger.isInfoEnabled()) { |
|
|
|
|
logger.info(String.format("Detected default resource location \"%s\" for test class [%s]", |
|
|
|
|
prefixedResourcePath, clazz.getName())); |
|
|
|
|
prefixedResourcePath, clazz.getName())); |
|
|
|
|
} |
|
|
|
|
return new String[] { prefixedResourcePath }; |
|
|
|
|
return new String[] {prefixedResourcePath}; |
|
|
|
|
} |
|
|
|
|
else if (logger.isDebugEnabled()) { |
|
|
|
|
logger.debug(String.format("Did not detect default resource location for test class [%s]: " |
|
|
|
|
+ "%s does not exist", clazz.getName(), classPathResource)); |
|
|
|
|
logger.debug(String.format("Did not detect default resource location for test class [%s]: " + |
|
|
|
|
"%s does not exist", clazz.getName(), classPathResource)); |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
if (logger.isInfoEnabled()) { |
|
|
|
|
logger.info(String.format("Could not detect default resource locations for test class [%s]: " |
|
|
|
|
+ "no resource found for suffixes %s.", clazz.getName(), ObjectUtils.nullSafeToString(suffixes))); |
|
|
|
|
logger.info(String.format("Could not detect default resource locations for test class [%s]: " + |
|
|
|
|
"no resource found for suffixes %s.", clazz.getName(), ObjectUtils.nullSafeToString(suffixes))); |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
return EMPTY_STRING_ARRAY; |
|
|
|
@ -282,36 +282,31 @@ public abstract class AbstractContextLoader implements SmartContextLoader {
@@ -282,36 +282,31 @@ public abstract class AbstractContextLoader implements SmartContextLoader {
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Get the suffix to append to {@link ApplicationContext} resource |
|
|
|
|
* locations when detecting default locations. |
|
|
|
|
* |
|
|
|
|
* <p>Subclasses must provide an implementation of this method that |
|
|
|
|
* returns a single suffix. Alternatively subclasses may provide a |
|
|
|
|
* <em>no-op</em> implementation of this method and override |
|
|
|
|
* {@link #getResourceSuffixes()} in order to provide multiple custom |
|
|
|
|
* suffixes. |
|
|
|
|
* |
|
|
|
|
* @return the resource suffix; never {@code null} or empty |
|
|
|
|
* @since 2.5 |
|
|
|
|
* @see #generateDefaultLocations(Class) |
|
|
|
|
* @see #getResourceSuffixes() |
|
|
|
|
*/ |
|
|
|
|
protected abstract String getResourceSuffix(); |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Get the suffixes to append to {@link ApplicationContext} resource |
|
|
|
|
* locations when detecting default locations. |
|
|
|
|
* |
|
|
|
|
* Get the suffixes to append to {@link ApplicationContext} resource locations |
|
|
|
|
* when detecting default locations. |
|
|
|
|
* <p>The default implementation simply wraps the value returned by |
|
|
|
|
* {@link #getResourceSuffix()} in a single-element array, but this |
|
|
|
|
* can be overridden by subclasses in order to support multiple suffixes. |
|
|
|
|
* |
|
|
|
|
* @return the resource suffixes; never {@code null} or empty |
|
|
|
|
* @since 4.1 |
|
|
|
|
* @see #generateDefaultLocations(Class) |
|
|
|
|
*/ |
|
|
|
|
protected String[] getResourceSuffixes() { |
|
|
|
|
return new String[] { getResourceSuffix() }; |
|
|
|
|
return new String[] {getResourceSuffix()}; |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
/** |
|
|
|
|
* Get the suffix to append to {@link ApplicationContext} resource locations |
|
|
|
|
* when detecting default locations. |
|
|
|
|
* <p>Subclasses must provide an implementation of this method that returns |
|
|
|
|
* a single suffix. Alternatively subclasses may provide a <em>no-op</em> |
|
|
|
|
* implementation of this method and override {@link #getResourceSuffixes()} |
|
|
|
|
* in order to provide multiple custom suffixes. |
|
|
|
|
* @return the resource suffix; never {@code null} or empty |
|
|
|
|
* @since 2.5 |
|
|
|
|
* @see #generateDefaultLocations(Class) |
|
|
|
|
* @see #getResourceSuffixes() |
|
|
|
|
*/ |
|
|
|
|
protected abstract String getResourceSuffix(); |
|
|
|
|
|
|
|
|
|
} |
|
|
|
|