@ -32,7 +32,7 @@ import org.springframework.util.StringUtils;
@@ -32,7 +32,7 @@ import org.springframework.util.StringUtils;
/ * *
* Utility methods for working with { @link ContextLoader ContextLoaders } .
*
* < p > TODO : Consider refactoring into a stateful ContextLoaderResolver .
* < p > TODO Consider refactoring into a stateful ContextLoaderResolver .
*
* @author Sam Brannen
* @since 3 . 1
@ -44,6 +44,9 @@ public abstract class ContextLoaderUtils {
@@ -44,6 +44,9 @@ public abstract class ContextLoaderUtils {
private static final String STANDARD_DEFAULT_CONTEXT_LOADER_CLASS_NAME = "org.springframework.test.context.support.GenericXmlContextLoader" ;
private static final ClassNameLocationsResolver classNameLocationsResolver = new ClassNameLocationsResolver ( ) ;
private static final ResourcePathLocationsResolver resourcePathLocationsResolver = new ResourcePathLocationsResolver ( ) ;
/ * *
* TODO Document resolveContextLoader ( ) .
@ -164,91 +167,82 @@ public abstract class ContextLoaderUtils {
@@ -164,91 +167,82 @@ public abstract class ContextLoaderUtils {
Class < ContextConfiguration > annotationType = ContextConfiguration . class ;
Class < ? > declaringClass = AnnotationUtils . findAnnotationDeclaringClass ( annotationType , clazz ) ;
Assert . notNull ( declaringClass , "Could not find an 'annotation declaring class' for annotation type ["
+ annotationType + "] and class [" + clazz + "]" ) ;
Assert . notNull ( declaringClass , String . format (
"Could not find an 'annotation declaring class' for annotation type [%s] and class [%s]" , annotationType ,
clazz ) ) ;
boolean processConfigurationClasses = ( contextLoader instanceof ResourceTypeAwareContextLoader )
& & ( ( ResourceTypeAwareContextLoader ) contextLoader ) . supportsClassResources ( ) ;
return processConfigurationClasses ? //
resolveConfigurationClassNames ( contextLoader , annotationType , declaringClass )
: resolveStringLocations ( contextLoader , annotationType , declaringClass ) ;
}
/ * *
* TODO Document resolveStringLocations ( ) .
*
* @param contextLoader
* @param annotationType
* @param declaringClass
* @return
* /
private static String [ ] resolveStringLocations ( ContextLoader contextLoader ,
Class < ContextConfiguration > annotationType , Class < ? > declaringClass ) {
LocationsResolver locationsResolver = processConfigurationClasses ? classNameLocationsResolver
: resourcePathLocationsResolver ;
List < String > locationsList = new ArrayList < String > ( ) ;
while ( declaringClass ! = null ) {
ContextConfiguration contextConfiguration = declaringClass . getAnnotation ( annotationType ) ;
if ( logger . isTraceEnabled ( ) ) {
logger . trace ( String . format ( "Retrieved @ContextConfiguration [%s] for declaring class [%s]." ,
contextConfiguration , declaringClass ) ) ;
}
String [ ] valueLocations = contextConfiguration . value ( ) ;
String [ ] resolvedLocations = locationsResolver . resolveLocations ( contextConfiguration , declaringClass ) ;
String [ ] processedLocations = contextLoader . processLocations ( declaringClass , resolvedLocations ) ;
locationsList . addAll ( 0 , Arrays . < String > asList ( processedLocations ) ) ;
declaringClass = contextConfiguration . inheritLocations ( ) ? AnnotationUtils . findAnnotationDeclaringClass (
annotationType , declaringClass . getSuperclass ( ) ) : null ;
}
return locationsList . toArray ( new String [ locationsList . size ( ) ] ) ;
}
private static interface LocationsResolver {
String [ ] resolveLocations ( ContextConfiguration contextConfiguration , Class < ? > declaringClass ) ;
}
private static final class ResourcePathLocationsResolver implements LocationsResolver {
public String [ ] resolveLocations ( ContextConfiguration contextConfiguration , Class < ? > declaringClass ) {
String [ ] locations = contextConfiguration . locations ( ) ;
String [ ] valueLocations = contextConfiguration . value ( ) ;
if ( ! ObjectUtils . isEmpty ( valueLocations ) & & ! ObjectUtils . isEmpty ( locations ) ) {
String msg = String . format (
"Test class [%s] has been configured with @ContextConfiguration's 'value' [%s] and 'locations' [%s] attributes. Only one declaration of resource locations is permitted per @ContextConfiguration annotation." ,
declaringClass , ObjectUtils . nullSafeToString ( valueLocations ) ,
ObjectUtils . nullSafeToString ( locations ) ) ;
logger . error ( msg ) ;
ContextLoaderUtils . logger . error ( msg ) ;
throw new IllegalStateException ( msg ) ;
}
else if ( ! ObjectUtils . isEmpty ( valueLocations ) ) {
locations = valueLocations ;
}
locations = contextLoader . processLocations ( declaringClass , locations ) ;
locationsList . addAll ( 0 , Arrays . < String > asList ( locations ) ) ;
declaringClass = contextConfiguration . inheritLocations ( ) ? AnnotationUtils . findAnnotationDeclaringClass (
annotationType , declaringClass . getSuperclass ( ) ) : null ;
return locations ;
}
return locationsList . toArray ( new String [ locationsList . size ( ) ] ) ;
}
/ * *
* TODO Document resolveConfigClassNames ( ) .
*
* @param contextLoader
* @param annotationType
* @param declaringClass
* @return
* /
private static String [ ] resolveConfigurationClassNames ( ContextLoader contextLoader ,
Class < ContextConfiguration > annotationType , Class < ? > declaringClass ) {
private static final class ClassNameLocationsResolver implements LocationsResolver {
// TODO [SPR-6184] Implement recursive search for configuration classes.
public String [ ] resolveLocations ( ContextConfiguration contextConfiguration , Class < ? > declaringClass ) {
ContextConfiguration contextConfiguration = declaringClass . getAnnotation ( annotationType ) ;
if ( logger . isTraceEnabled ( ) ) {
logger . trace ( String . format ( "Retrieved @ContextConfiguration [%s] for declaring class [%s]." ,
contextConfiguration , declaringClass ) ) ;
}
String [ ] classNames = null ;
String [ ] classNames = null ;
Class < ? > [ ] configClasses = contextConfiguration . classes ( ) ;
if ( ! ObjectUtils . isEmpty ( configClasses ) ) {
classNames = new String [ configClasses . length ] ;
Class < ? > [ ] configClasses = contextConfiguration . classes ( ) ;
if ( ! ObjectUtils . isEmpty ( configClasses ) ) {
classNames = new String [ configClasses . length ] ;
for ( int i = 0 ; i < configClasses . length ; i + + ) {
classNames [ i ] = configClasses [ i ] . getName ( ) ;
for ( int i = 0 ; i < configClasses . length ; i + + ) {
classNames [ i ] = configClasses [ i ] . getName ( ) ;
}
}
}
return contextLoader . processLocations ( declaringClass , classNames ) ;
return classNames ;
}
}
}