@@ -56,146 +56,93 @@ private ContextLoaderUtils() {
5656 /* no-op */
5757 }
5858
59- /**
60- * Resolve the list of {@link ContextConfigurationAttributes configuration
61- * attributes} for the supplied {@link Class class} and its superclasses.
62- * <p>Note that the {@link ContextConfiguration#inheritLocations
63- * inheritLocations} flag of {@link ContextConfiguration
64- * @ContextConfiguration} will be taken into consideration.
65- * Specifically, if the <code>inheritLocations</code> flag is set to
66- * <code>true</code>, configuration attributes defined in the annotated
67- * class will be appended to the configuration attributes defined in
68- * superclasses.
69- * @param clazz the class for which to resolve the configuration attributes (must
70- * not be <code>null</code>)
71- * @return the list of configuration attributes for the specified class,
72- * including configuration attributes from superclasses if appropriate
73- * (never <code>null</code>)
74- * @throws IllegalArgumentException if the supplied class is <code>null</code>
75- * or if {@link ContextConfiguration @ContextConfiguration} is not
76- * <em>present</em> on the supplied class
77- */
78- static List <ContextConfigurationAttributes > resolveContextConfigurationAttributes (Class <?> clazz ) {
79- Assert .notNull (clazz , "Class must not be null" );
80-
81- final List <ContextConfigurationAttributes > attributesList = new ArrayList <ContextConfigurationAttributes >();
82-
83- Class <ContextConfiguration > annotationType = ContextConfiguration .class ;
84- Class <?> declaringClass = AnnotationUtils .findAnnotationDeclaringClass (annotationType , clazz );
85- Assert .notNull (declaringClass , String .format (
86- "Could not find an 'annotation declaring class' for annotation type [%s] and class [%s]" , annotationType ,
87- clazz ));
88-
89- while (declaringClass != null ) {
90- ContextConfiguration contextConfiguration = declaringClass .getAnnotation (annotationType );
91-
92- if (logger .isTraceEnabled ()) {
93- logger .trace (String .format ("Retrieved @ContextConfiguration [%s] for declaring class [%s]." ,
94- contextConfiguration , declaringClass ));
95- }
96-
97- ContextConfigurationAttributes attributes = new ContextConfigurationAttributes (declaringClass ,
98- contextConfiguration );
99- if (logger .isTraceEnabled ()) {
100- logger .trace ("Resolved context configuration attributes: " + attributes );
101- }
102-
103- attributesList .add (0 , attributes );
104-
105- declaringClass = contextConfiguration .inheritLocations () ? AnnotationUtils .findAnnotationDeclaringClass (
106- annotationType , declaringClass .getSuperclass ()) : null ;
107- }
108-
109- return attributesList ;
110- }
111-
11259 /**
11360 * Resolve the {@link ContextLoader} {@link Class class} to use for the
114- * supplied {@link Class testClass} and {@link ContextConfigurationAttributes}
115- * and then instantiate and return that {@code ContextLoader}.
61+ * supplied {@link Class testClass} and then instantiate and return that
62+ * {@code ContextLoader}.
11663 * <p>If the supplied <code>defaultContextLoaderClassName</code> is
11764 * <code>null</code> or <em>empty</em>, the <em>standard</em>
11865 * default context loader class name {@value #DEFAULT_CONTEXT_LOADER_CLASS_NAME}
11966 * will be used. For details on the class resolution process, see
12067 * {@link #resolveContextLoaderClass()}.
12168 * @param testClass the test class for which the {@code ContextLoader}
12269 * should be resolved (must not be <code>null</code>)
123- * @param configAttributesList the resolved configuration attributes for the
124- * test class hierarchy
12570 * @param defaultContextLoaderClassName the name of the default
12671 * {@code ContextLoader} class to use (may be <code>null</code>)
12772 * @return the resolved {@code ContextLoader} for the supplied
12873 * <code>testClass</code> (never <code>null</code>)
12974 * @see #resolveContextLoaderClass()
130- * @see #resolveContextConfigurationAttributes()
13175 */
132- static ContextLoader resolveContextLoader (Class <?> testClass ,
133- List <ContextConfigurationAttributes > configAttributesList , String defaultContextLoaderClassName ) {
76+ static ContextLoader resolveContextLoader (Class <?> testClass , String defaultContextLoaderClassName ) {
13477 Assert .notNull (testClass , "Test class must not be null" );
135- Assert .notEmpty (configAttributesList , "ContextConfigurationAttributes list must not be null or empty" );
13678
13779 if (!StringUtils .hasText (defaultContextLoaderClassName )) {
13880 defaultContextLoaderClassName = DEFAULT_CONTEXT_LOADER_CLASS_NAME ;
13981 }
14082
141- Class <? extends ContextLoader > contextLoaderClass = resolveContextLoaderClass (testClass , configAttributesList ,
83+ Class <? extends ContextLoader > contextLoaderClass = resolveContextLoaderClass (testClass ,
14284 defaultContextLoaderClassName );
14385
14486 return (ContextLoader ) BeanUtils .instantiateClass (contextLoaderClass );
14587 }
14688
14789 /**
14890 * Resolve the {@link ContextLoader} {@link Class} to use for the supplied
149- * {@link ContextConfigurationAttributes} list.
150- * <p>This method will iterate over the supplied configuration attributes
151- * and execute the following algorithm:
91+ * {@link Class testClass}.
15292 * <ol>
153- * <li>If {@link ContextConfigurationAttributes#getContextLoaderClass()}
154- * returns an explicit implementation class, that class will be returned.</li>
155- * <li>If an explicit {@code ContextLoader} implementation class is not
156- * specified, the next {@link ContextConfigurationAttributes} instance in
157- * the supplied list will be processed; go to step #1.</li>
158- * <li>If no explicit < code>loader</code> class is found after processing
159- * all {@link ContextConfigurationAttributes} instances, an attempt will be
160- * made to load and return the class with the supplied
161- * <code>defaultContextLoaderClassName</code>.</li>
93+ * <li>If the {@link ContextConfiguration#loader() loader} attribute of
94+ * {@link ContextConfiguration @ContextConfiguration} is configured
95+ * with an explicit class, that class will be returned.</li>
96+ * <li>If a <code>loader</code> class is not specified, the class hierarchy
97+ * will be traversed to find a parent class annotated with
98+ * {@ code @ContextConfiguration}; go to step #1.</li>
99+ * <li>If no explicit <code>loader</code> class is found after traversing
100+ * the class hierarchy, an attempt will be made to load and return the class
101+ * with the supplied <code>defaultContextLoaderClassName</code>.</li>
162102 * </ol>
163103 * @param testClass the class for which to resolve the {@code ContextLoader}
164- * class; used solely for logging purposes; must not be <code>null</code>
165- * @param configAttributesList the resolved configuration attributes for the
166- * test class hierarchy; must not be <code>null</code> or empty
104+ * class; must not be <code>null</code>
167105 * @param defaultContextLoaderClassName the name of the default
168106 * {@code ContextLoader} class to use; must not be <code>null</code> or empty
169- * @return the {@code ContextLoader} class to use for the specified class
170- * (never <code>null</code>)
107+ * @return the {@code ContextLoader} class to use for the supplied test class
171108 * @throws IllegalArgumentException if {@code @ContextConfiguration} is not
172- * <em>present</em> on the supplied test class
173- * @see #resolveContextLoader()
174- * @see #resolveContextConfigurationAttributes()
109+ * <em>present</em> on the supplied test class
110+ * @throws IllegalStateException if the default {@code ContextLoader} class
111+ * could not be loaded
175112 */
176113 @ SuppressWarnings ("unchecked" )
177114 static Class <? extends ContextLoader > resolveContextLoaderClass (Class <?> testClass ,
178- List < ContextConfigurationAttributes > configAttributesList , String defaultContextLoaderClassName ) {
115+ String defaultContextLoaderClassName ) {
179116 Assert .notNull (testClass , "Class must not be null" );
180- Assert .notEmpty (configAttributesList , "ContextConfigurationAttributes list must not be null or empty" );
181117 Assert .hasText (defaultContextLoaderClassName , "Default ContextLoader class name must not be null or empty" );
182118
183- for (ContextConfigurationAttributes configAttributes : configAttributesList ) {
119+ Class <ContextConfiguration > annotationType = ContextConfiguration .class ;
120+ Class <?> declaringClass = AnnotationUtils .findAnnotationDeclaringClass (annotationType , testClass );
121+ Assert .notNull (declaringClass , String .format (
122+ "Could not find an 'annotation declaring class' for annotation type [%s] and test class [%s]" ,
123+ annotationType , testClass ));
124+
125+ while (declaringClass != null ) {
126+ ContextConfiguration contextConfiguration = declaringClass .getAnnotation (annotationType );
127+
184128 if (logger .isTraceEnabled ()) {
185129 logger .trace (String .format (
186- "Processing ContextLoader for context configuration attributes [%s] and test class [%s]" ,
187- configAttributes , testClass ));
130+ "Processing ContextLoader for @ContextConfiguration [%s] and declaring class [%s]" ,
131+ contextConfiguration , declaringClass ));
188132 }
189133
190- Class <? extends ContextLoader > contextLoaderClass = configAttributes . getContextLoaderClass ();
134+ Class <? extends ContextLoader > contextLoaderClass = contextConfiguration . loader ();
191135 if (!ContextLoader .class .equals (contextLoaderClass )) {
192136 if (logger .isDebugEnabled ()) {
193137 logger .debug (String .format (
194- "Found explicit ContextLoader class [%s] for context configuration attributes [%s] and test class [%s]" ,
195- contextLoaderClass , configAttributes , testClass ));
138+ "Found explicit ContextLoader class [%s] for @ContextConfiguration [%s] and declaring class [%s]" ,
139+ contextLoaderClass , contextConfiguration , declaringClass ));
196140 }
197141 return contextLoaderClass ;
198142 }
143+
144+ declaringClass = AnnotationUtils .findAnnotationDeclaringClass (annotationType ,
145+ declaringClass .getSuperclass ());
199146 }
200147
201148 try {
@@ -213,6 +160,58 @@ static Class<? extends ContextLoader> resolveContextLoaderClass(Class<?> testCla
213160 }
214161 }
215162
163+ /**
164+ * Resolve the list of {@link ContextConfigurationAttributes configuration
165+ * attributes} for the supplied {@link Class class} and its superclasses.
166+ * <p>Note that the {@link ContextConfiguration#inheritLocations
167+ * inheritLocations} flag of {@link ContextConfiguration
168+ * @ContextConfiguration} will be taken into consideration.
169+ * Specifically, if the <code>inheritLocations</code> flag is set to
170+ * <code>true</code>, configuration attributes defined in the annotated
171+ * class will be appended to the configuration attributes defined in
172+ * superclasses.
173+ * @param clazz the class for which to resolve the configuration attributes (must
174+ * not be <code>null</code>)
175+ * @return the list of configuration attributes for the specified class,
176+ * including configuration attributes from superclasses if appropriate
177+ * (never <code>null</code>)
178+ * @throws IllegalArgumentException if the supplied class is <code>null</code> or
179+ * if {@code @ContextConfiguration} is not <em>present</em> on the supplied class
180+ */
181+ static List <ContextConfigurationAttributes > resolveContextConfigurationAttributes (Class <?> clazz ) {
182+ Assert .notNull (clazz , "Class must not be null" );
183+
184+ final List <ContextConfigurationAttributes > attributesList = new ArrayList <ContextConfigurationAttributes >();
185+
186+ Class <ContextConfiguration > annotationType = ContextConfiguration .class ;
187+ Class <?> declaringClass = AnnotationUtils .findAnnotationDeclaringClass (annotationType , clazz );
188+ Assert .notNull (declaringClass , String .format (
189+ "Could not find an 'annotation declaring class' for annotation type [%s] and class [%s]" , annotationType ,
190+ clazz ));
191+
192+ while (declaringClass != null ) {
193+ ContextConfiguration contextConfiguration = declaringClass .getAnnotation (annotationType );
194+
195+ if (logger .isTraceEnabled ()) {
196+ logger .trace (String .format ("Retrieved @ContextConfiguration [%s] for declaring class [%s]." ,
197+ contextConfiguration , declaringClass ));
198+ }
199+
200+ ContextConfigurationAttributes attributes = new ContextConfigurationAttributes (declaringClass ,
201+ contextConfiguration );
202+ if (logger .isTraceEnabled ()) {
203+ logger .trace ("Resolved context configuration attributes: " + attributes );
204+ }
205+
206+ attributesList .add (0 , attributes );
207+
208+ declaringClass = contextConfiguration .inheritLocations () ? AnnotationUtils .findAnnotationDeclaringClass (
209+ annotationType , declaringClass .getSuperclass ()) : null ;
210+ }
211+
212+ return attributesList ;
213+ }
214+
216215 /**
217216 * Resolve <em>active bean definition profiles</em> for the supplied {@link Class}.
218217 * <p>Note that the {@link ActiveProfiles#inheritProfiles inheritProfiles}
@@ -286,8 +285,8 @@ else if (!ObjectUtils.isEmpty(valueProfiles)) {
286285 * @param defaultContextLoaderClassName the name of the default
287286 * {@code ContextLoader} class to use (may be <code>null</code>)
288287 * @return the merged context configuration
289- * @see #resolveContextConfigurationAttributes()
290288 * @see #resolveContextLoader()
289+ * @see #resolveContextConfigurationAttributes()
291290 * @see SmartContextLoader#processContextConfiguration()
292291 * @see ContextLoader#processLocations()
293292 * @see #resolveActiveProfiles()
@@ -296,16 +295,8 @@ else if (!ObjectUtils.isEmpty(valueProfiles)) {
296295 static MergedContextConfiguration buildMergedContextConfiguration (Class <?> testClass ,
297296 String defaultContextLoaderClassName ) {
298297
299- List <ContextConfigurationAttributes > configAttributesList = resolveContextConfigurationAttributes (testClass );
300-
301- ContextLoader contextLoader = resolveContextLoader (testClass , configAttributesList ,
302- defaultContextLoaderClassName );
303-
304- // Algorithm:
305- // - iterate over config attributes
306- // -- let loader process locations
307- // -- let loader process classes, if it's a SmartContextLoader
308-
298+ final ContextLoader contextLoader = resolveContextLoader (testClass , defaultContextLoaderClassName );
299+ final List <ContextConfigurationAttributes > configAttributesList = resolveContextConfigurationAttributes (testClass );
309300 final List <String > locationsList = new ArrayList <String >();
310301 final List <Class <?>> classesList = new ArrayList <Class <?>>();
311302
0 commit comments