29 changed files with 1474 additions and 601 deletions
@ -1,94 +0,0 @@
@@ -1,94 +0,0 @@
|
||||
/* |
||||
* Copyright 2002-2012 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. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
package org.springframework.test.web.mock.servlet.samples.context; |
||||
|
||||
import javax.servlet.RequestDispatcher; |
||||
|
||||
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; |
||||
import org.springframework.context.ApplicationContext; |
||||
import org.springframework.context.annotation.AnnotatedBeanDefinitionReader; |
||||
import org.springframework.context.annotation.AnnotationConfigUtils; |
||||
import org.springframework.core.io.DefaultResourceLoader; |
||||
import org.springframework.core.io.FileSystemResourceLoader; |
||||
import org.springframework.core.io.ResourceLoader; |
||||
import org.springframework.mock.web.MockRequestDispatcher; |
||||
import org.springframework.mock.web.MockServletContext; |
||||
import org.springframework.test.context.MergedContextConfiguration; |
||||
import org.springframework.test.context.support.AbstractContextLoader; |
||||
import org.springframework.web.context.WebApplicationContext; |
||||
import org.springframework.web.context.support.GenericWebApplicationContext; |
||||
|
||||
/** |
||||
* This class is here temporarily until the TestContext framework provides |
||||
* support for WebApplicationContext yet: |
||||
* |
||||
* https://jira.springsource.org/browse/SPR-5243
|
||||
* |
||||
* <p>After that this class will no longer be needed. It's provided here as an example |
||||
* and to serve as a temporary solution. |
||||
*/ |
||||
public class GenericWebContextLoader extends AbstractContextLoader { |
||||
protected final MockServletContext servletContext; |
||||
|
||||
public GenericWebContextLoader(String warRootDir, boolean isClasspathRelative) { |
||||
ResourceLoader resourceLoader = isClasspathRelative ? new DefaultResourceLoader() : new FileSystemResourceLoader(); |
||||
this.servletContext = initServletContext(warRootDir, resourceLoader); |
||||
} |
||||
|
||||
private MockServletContext initServletContext(String warRootDir, ResourceLoader resourceLoader) { |
||||
return new MockServletContext(warRootDir, resourceLoader) { |
||||
// Required for DefaultServletHttpRequestHandler...
|
||||
public RequestDispatcher getNamedDispatcher(String path) { |
||||
return (path.equals("default")) ? new MockRequestDispatcher(path) : super.getNamedDispatcher(path); |
||||
} |
||||
}; |
||||
} |
||||
|
||||
public ApplicationContext loadContext(MergedContextConfiguration mergedConfig) throws Exception { |
||||
GenericWebApplicationContext context = new GenericWebApplicationContext(); |
||||
context.getEnvironment().setActiveProfiles(mergedConfig.getActiveProfiles()); |
||||
prepareContext(context); |
||||
loadBeanDefinitions(context, mergedConfig); |
||||
return context; |
||||
} |
||||
|
||||
public ApplicationContext loadContext(String... locations) throws Exception { |
||||
// should never be called
|
||||
throw new UnsupportedOperationException(); |
||||
} |
||||
|
||||
protected void prepareContext(GenericWebApplicationContext context) { |
||||
this.servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, context); |
||||
context.setServletContext(this.servletContext); |
||||
} |
||||
|
||||
protected void loadBeanDefinitions(GenericWebApplicationContext context, String[] locations) { |
||||
new XmlBeanDefinitionReader(context).loadBeanDefinitions(locations); |
||||
AnnotationConfigUtils.registerAnnotationConfigProcessors(context); |
||||
context.refresh(); |
||||
context.registerShutdownHook(); |
||||
} |
||||
|
||||
protected void loadBeanDefinitions(GenericWebApplicationContext context, MergedContextConfiguration mergedConfig) { |
||||
new AnnotatedBeanDefinitionReader(context).register(mergedConfig.getClasses()); |
||||
loadBeanDefinitions(context, mergedConfig.getLocations()); |
||||
} |
||||
|
||||
@Override |
||||
protected String getResourceSuffix() { |
||||
return "-context.xml"; |
||||
} |
||||
} |
||||
@ -0,0 +1,287 @@
@@ -0,0 +1,287 @@
|
||||
/* |
||||
* Copyright 2002-2012 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. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.test.context.support; |
||||
|
||||
import java.util.Arrays; |
||||
import java.util.List; |
||||
|
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
|
||||
import org.springframework.context.ApplicationContext; |
||||
import org.springframework.test.context.ContextConfiguration; |
||||
import org.springframework.test.context.ContextConfigurationAttributes; |
||||
import org.springframework.test.context.ContextLoader; |
||||
import org.springframework.test.context.MergedContextConfiguration; |
||||
import org.springframework.test.context.SmartContextLoader; |
||||
import org.springframework.util.Assert; |
||||
import org.springframework.util.ObjectUtils; |
||||
|
||||
/** |
||||
* {@code AbstractDelegatingSmartContextLoader} serves as an abstract base class
|
||||
* for implementations of the {@link SmartContextLoader} SPI that delegate to a |
||||
* set of <em>candidate</em> SmartContextLoaders (i.e., one that supports XML |
||||
* configuration files and one that supports annotated classes) to determine which |
||||
* context loader is appropriate for a given test class's configuration. Each |
||||
* candidate is given a chance to {@link #processContextConfiguration process} the |
||||
* {@link ContextConfigurationAttributes} for each class in the test class hierarchy |
||||
* that is annotated with {@link ContextConfiguration @ContextConfiguration}, and |
||||
* the candidate that supports the merged, processed configuration will be used to |
||||
* actually {@link #loadContext load} the context. |
||||
* |
||||
* <p>Placing an empty {@code @ContextConfiguration} annotation on a test class signals |
||||
* that default resource locations (i.e., XML configuration files) or default |
||||
* {@link org.springframework.context.annotation.Configuration configuration classes} |
||||
* should be detected. Furthermore, if a specific {@link ContextLoader} or |
||||
* {@link SmartContextLoader} is not explicitly declared via |
||||
* {@code @ContextConfiguration}, a concrete subclass of |
||||
* {@code AbstractDelegatingSmartContextLoader} will be used as the default loader, |
||||
* thus providing automatic support for either XML configuration files or annotated |
||||
* classes, but not both simultaneously. |
||||
* |
||||
* <p>As of Spring 3.2, a test class may optionally declare neither XML configuration |
||||
* files nor annotated classes and instead declare only {@linkplain |
||||
* ContextConfiguration#initializers application context initializers}. In such |
||||
* cases, an attempt will still be made to detect defaults, but their absence will |
||||
* not result an an exception. |
||||
* |
||||
* @author Sam Brannen |
||||
* @since 3.2 |
||||
* @see SmartContextLoader |
||||
*/ |
||||
abstract class AbstractDelegatingSmartContextLoader implements SmartContextLoader { |
||||
|
||||
private static final Log logger = LogFactory.getLog(AbstractDelegatingSmartContextLoader.class); |
||||
|
||||
|
||||
/** |
||||
* Get the delegate {@code SmartContextLoader} that supports XML configuration files. |
||||
*/ |
||||
protected abstract SmartContextLoader getXmlLoader(); |
||||
|
||||
/** |
||||
* Get the delegate {@code SmartContextLoader} that supports annotated classes. |
||||
*/ |
||||
protected abstract SmartContextLoader getAnnotationConfigLoader(); |
||||
|
||||
// --- SmartContextLoader --------------------------------------------------
|
||||
|
||||
private static String name(SmartContextLoader loader) { |
||||
return loader.getClass().getSimpleName(); |
||||
} |
||||
|
||||
private static void delegateProcessing(SmartContextLoader loader, ContextConfigurationAttributes configAttributes) { |
||||
if (logger.isDebugEnabled()) { |
||||
logger.debug(String.format("Delegating to %s to process context configuration %s.", name(loader), |
||||
configAttributes)); |
||||
} |
||||
loader.processContextConfiguration(configAttributes); |
||||
} |
||||
|
||||
private static ApplicationContext delegateLoading(SmartContextLoader loader, MergedContextConfiguration mergedConfig) |
||||
throws Exception { |
||||
if (logger.isDebugEnabled()) { |
||||
logger.debug(String.format("Delegating to %s to load context from %s.", name(loader), mergedConfig)); |
||||
} |
||||
return loader.loadContext(mergedConfig); |
||||
} |
||||
|
||||
private boolean supports(SmartContextLoader loader, MergedContextConfiguration mergedConfig) { |
||||
if (loader == getAnnotationConfigLoader()) { |
||||
return ObjectUtils.isEmpty(mergedConfig.getLocations()) && !ObjectUtils.isEmpty(mergedConfig.getClasses()); |
||||
} else { |
||||
return !ObjectUtils.isEmpty(mergedConfig.getLocations()) && ObjectUtils.isEmpty(mergedConfig.getClasses()); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Delegates to candidate {@code SmartContextLoaders} to process the supplied |
||||
* {@link ContextConfigurationAttributes}. |
||||
* |
||||
* <p>Delegation is based on explicit knowledge of the implementations of the |
||||
* default loaders for {@link #getXmlLoader() XML configuration files} and |
||||
* {@link #getAnnotationConfigLoader() annotated classes}. Specifically, the |
||||
* delegation algorithm is as follows: |
||||
* |
||||
* <ul> |
||||
* <li>If the resource locations or annotated classes in the supplied |
||||
* {@code ContextConfigurationAttributes} are not empty, the appropriate |
||||
* candidate loader will be allowed to process the configuration <em>as is</em>, |
||||
* without any checks for detection of defaults.</li> |
||||
* <li>Otherwise, the XML-based loader will be allowed to process |
||||
* the configuration in order to detect default resource locations. If |
||||
* the XML-based loader detects default resource locations, |
||||
* an {@code info} message will be logged.</li> |
||||
* <li>Subsequently, the annotation-based loader will be allowed to |
||||
* process the configuration in order to detect default configuration classes. |
||||
* If the annotation-based loader detects default configuration |
||||
* classes, an {@code info} message will be logged.</li> |
||||
* </ul> |
||||
* |
||||
* @param configAttributes the context configuration attributes to process |
||||
* @throws IllegalArgumentException if the supplied configuration attributes are |
||||
* <code>null</code>, or if the supplied configuration attributes include both |
||||
* resource locations and annotated classes |
||||
* @throws IllegalStateException if the XML-based loader detects default |
||||
* configuration classes; if the annotation-based loader detects default |
||||
* resource locations; if neither candidate loader detects defaults for the supplied |
||||
* context configuration; or if both candidate loaders detect defaults for the |
||||
* supplied context configuration |
||||
*/ |
||||
public void processContextConfiguration(final ContextConfigurationAttributes configAttributes) { |
||||
|
||||
Assert.notNull(configAttributes, "configAttributes must not be null"); |
||||
Assert.isTrue(!(configAttributes.hasLocations() && configAttributes.hasClasses()), String.format( |
||||
"Cannot process locations AND classes for context " |
||||
+ "configuration %s; configure one or the other, but not both.", configAttributes)); |
||||
|
||||
// If the original locations or classes were not empty, there's no
|
||||
// need to bother with default detection checks; just let the
|
||||
// appropriate loader process the configuration.
|
||||
if (configAttributes.hasLocations()) { |
||||
delegateProcessing(getXmlLoader(), configAttributes); |
||||
} else if (configAttributes.hasClasses()) { |
||||
delegateProcessing(getAnnotationConfigLoader(), configAttributes); |
||||
} else { |
||||
// Else attempt to detect defaults...
|
||||
|
||||
// Let the XML loader process the configuration.
|
||||
delegateProcessing(getXmlLoader(), configAttributes); |
||||
boolean xmlLoaderDetectedDefaults = configAttributes.hasLocations(); |
||||
|
||||
if (xmlLoaderDetectedDefaults) { |
||||
if (logger.isInfoEnabled()) { |
||||
logger.info(String.format("%s detected default locations for context configuration %s.", |
||||
name(getXmlLoader()), configAttributes)); |
||||
} |
||||
} |
||||
|
||||
if (configAttributes.hasClasses()) { |
||||
throw new IllegalStateException(String.format( |
||||
"%s should NOT have detected default configuration classes for context configuration %s.", |
||||
name(getXmlLoader()), configAttributes)); |
||||
} |
||||
|
||||
// Now let the annotation config loader process the configuration.
|
||||
delegateProcessing(getAnnotationConfigLoader(), configAttributes); |
||||
|
||||
if (configAttributes.hasClasses()) { |
||||
if (logger.isInfoEnabled()) { |
||||
logger.info(String.format( |
||||
"%s detected default configuration classes for context configuration %s.", |
||||
name(getAnnotationConfigLoader()), configAttributes)); |
||||
} |
||||
} |
||||
|
||||
if (!xmlLoaderDetectedDefaults && configAttributes.hasLocations()) { |
||||
throw new IllegalStateException(String.format( |
||||
"%s should NOT have detected default locations for context configuration %s.", |
||||
name(getAnnotationConfigLoader()), configAttributes)); |
||||
} |
||||
|
||||
// If neither loader detected defaults and no initializers were declared,
|
||||
// throw an exception.
|
||||
if (!configAttributes.hasResources() && ObjectUtils.isEmpty(configAttributes.getInitializers())) { |
||||
throw new IllegalStateException(String.format( |
||||
"Neither %s nor %s was able to detect defaults, and no ApplicationContextInitializers " |
||||
+ "were declared for context configuration %s", name(getXmlLoader()), |
||||
name(getAnnotationConfigLoader()), configAttributes)); |
||||
} |
||||
|
||||
if (configAttributes.hasLocations() && configAttributes.hasClasses()) { |
||||
String message = String.format( |
||||
"Configuration error: both default locations AND default configuration classes " |
||||
+ "were detected for context configuration %s; configure one or the other, but not both.", |
||||
configAttributes); |
||||
logger.error(message); |
||||
throw new IllegalStateException(message); |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Delegates to an appropriate candidate {@code SmartContextLoader} to load |
||||
* an {@link ApplicationContext}. |
||||
* |
||||
* <p>Delegation is based on explicit knowledge of the implementations of the |
||||
* default loaders for {@link #getXmlLoader() XML configuration files} and |
||||
* {@link #getAnnotationConfigLoader() annotated classes}. Specifically, the |
||||
* delegation algorithm is as follows: |
||||
* |
||||
* <ul> |
||||
* <li>If the resource locations in the supplied {@code MergedContextConfiguration} |
||||
* are not empty and the annotated classes are empty, |
||||
* the XML-based loader will load the {@code ApplicationContext}.</li> |
||||
* <li>If the annotated classes in the supplied {@code MergedContextConfiguration} |
||||
* are not empty and the resource locations are empty, |
||||
* the annotation-based loader will load the {@code ApplicationContext}.</li> |
||||
* </ul> |
||||
* |
||||
* @param mergedConfig the merged context configuration to use to load the application context |
||||
* @throws IllegalArgumentException if the supplied merged configuration is <code>null</code> |
||||
* @throws IllegalStateException if neither candidate loader is capable of loading an |
||||
* {@code ApplicationContext} from the supplied merged context configuration |
||||
*/ |
||||
public ApplicationContext loadContext(MergedContextConfiguration mergedConfig) throws Exception { |
||||
Assert.notNull(mergedConfig, "mergedConfig must not be null"); |
||||
|
||||
List<SmartContextLoader> candidates = Arrays.asList(getXmlLoader(), getAnnotationConfigLoader()); |
||||
|
||||
for (SmartContextLoader loader : candidates) { |
||||
// Determine if each loader can load a context from the mergedConfig. If it
|
||||
// can, let it; otherwise, keep iterating.
|
||||
if (supports(loader, mergedConfig)) { |
||||
return delegateLoading(loader, mergedConfig); |
||||
} |
||||
} |
||||
|
||||
// If neither of the candidates supports the mergedConfig based on resources but
|
||||
// ACIs were declared, then delegate to the annotation config loader.
|
||||
if (!mergedConfig.getContextInitializerClasses().isEmpty()) { |
||||
return delegateLoading(getAnnotationConfigLoader(), mergedConfig); |
||||
} |
||||
|
||||
throw new IllegalStateException(String.format( |
||||
"Neither %s nor %s was able to load an ApplicationContext from %s.", name(getXmlLoader()), |
||||
name(getAnnotationConfigLoader()), mergedConfig)); |
||||
} |
||||
|
||||
// --- ContextLoader -------------------------------------------------------
|
||||
|
||||
/** |
||||
* {@code AbstractDelegatingSmartContextLoader} does not support the |
||||
* {@link ContextLoader#processLocations(Class, String...)} method. Call |
||||
* {@link #processContextConfiguration(ContextConfigurationAttributes)} instead. |
||||
* @throws UnsupportedOperationException |
||||
*/ |
||||
public final String[] processLocations(Class<?> clazz, String... locations) { |
||||
throw new UnsupportedOperationException("DelegatingSmartContextLoaders do not support the ContextLoader SPI. " |
||||
+ "Call processContextConfiguration(ContextConfigurationAttributes) instead."); |
||||
} |
||||
|
||||
/** |
||||
* {@code AbstractDelegatingSmartContextLoader} does not support the |
||||
* {@link ContextLoader#loadContext(String...) } method. Call |
||||
* {@link #loadContext(MergedContextConfiguration)} instead. |
||||
* @throws UnsupportedOperationException |
||||
*/ |
||||
public final ApplicationContext loadContext(String... locations) throws Exception { |
||||
throw new UnsupportedOperationException("DelegatingSmartContextLoaders do not support the ContextLoader SPI. " |
||||
+ "Call loadContext(MergedContextConfiguration) instead."); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,126 @@
@@ -0,0 +1,126 @@
|
||||
/* |
||||
* Copyright 2002-2012 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. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.test.context.support; |
||||
|
||||
import javax.servlet.ServletContext; |
||||
|
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
import org.springframework.beans.factory.support.DefaultListableBeanFactory; |
||||
import org.springframework.context.ApplicationContext; |
||||
import org.springframework.context.ConfigurableApplicationContext; |
||||
import org.springframework.context.annotation.AnnotationConfigUtils; |
||||
import org.springframework.core.io.DefaultResourceLoader; |
||||
import org.springframework.core.io.FileSystemResourceLoader; |
||||
import org.springframework.core.io.ResourceLoader; |
||||
import org.springframework.mock.web.MockServletContext; |
||||
import org.springframework.test.context.MergedContextConfiguration; |
||||
import org.springframework.test.context.web.WebMergedContextConfiguration; |
||||
import org.springframework.web.context.WebApplicationContext; |
||||
import org.springframework.web.context.support.GenericWebApplicationContext; |
||||
|
||||
/** |
||||
* TODO [SPR-5243] Document AbstractGenericWebContextLoader. |
||||
* |
||||
* @author Sam Brannen |
||||
* @since 3.2 |
||||
*/ |
||||
public abstract class AbstractGenericWebContextLoader extends AbstractContextLoader { |
||||
|
||||
private static final Log logger = LogFactory.getLog(AbstractGenericWebContextLoader.class); |
||||
|
||||
|
||||
// --- SmartContextLoader -----------------------------------------------
|
||||
|
||||
/** |
||||
* TODO [SPR-5243] Document overridden loadContext(MergedContextConfiguration). |
||||
* |
||||
* @see org.springframework.test.context.SmartContextLoader#loadContext(org.springframework.test.context.MergedContextConfiguration) |
||||
*/ |
||||
public final ConfigurableApplicationContext loadContext(MergedContextConfiguration mergedConfig) throws Exception { |
||||
|
||||
if (!(mergedConfig instanceof WebMergedContextConfiguration)) { |
||||
throw new IllegalArgumentException(String.format( |
||||
"Cannot load WebApplicationContext from non-web merged context configuration %s. " |
||||
+ "Consider annotating your test class with @WebAppConfiguration.", mergedConfig)); |
||||
} |
||||
WebMergedContextConfiguration webMergedConfig = (WebMergedContextConfiguration) mergedConfig; |
||||
|
||||
if (logger.isDebugEnabled()) { |
||||
logger.debug(String.format("Loading WebApplicationContext for merged context configuration %s.", |
||||
webMergedConfig)); |
||||
} |
||||
|
||||
GenericWebApplicationContext context = new GenericWebApplicationContext(); |
||||
configureWebResources(context, webMergedConfig); |
||||
prepareContext(context, webMergedConfig); |
||||
customizeBeanFactory(context.getDefaultListableBeanFactory(), webMergedConfig); |
||||
loadBeanDefinitions(context, webMergedConfig); |
||||
AnnotationConfigUtils.registerAnnotationConfigProcessors(context); |
||||
customizeContext(context, webMergedConfig); |
||||
context.refresh(); |
||||
context.registerShutdownHook(); |
||||
return context; |
||||
} |
||||
|
||||
/** |
||||
* TODO [SPR-5243] Document configureWebResources(). |
||||
*/ |
||||
protected void configureWebResources(GenericWebApplicationContext context, |
||||
WebMergedContextConfiguration webMergedConfig) { |
||||
|
||||
String resourceBasePath = webMergedConfig.getResourceBasePath(); |
||||
ResourceLoader resourceLoader = resourceBasePath.startsWith(ResourceLoader.CLASSPATH_URL_PREFIX) ? new DefaultResourceLoader() |
||||
: new FileSystemResourceLoader(); |
||||
|
||||
ServletContext servletContext = new MockServletContext(resourceBasePath, resourceLoader); |
||||
servletContext.setAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, context); |
||||
context.setServletContext(servletContext); |
||||
} |
||||
|
||||
/** |
||||
* TODO [SPR-5243] Document customizeBeanFactory(). |
||||
*/ |
||||
protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory, |
||||
WebMergedContextConfiguration webMergedConfig) { |
||||
} |
||||
|
||||
/** |
||||
* TODO [SPR-5243] Document loadBeanDefinitions(). |
||||
*/ |
||||
protected abstract void loadBeanDefinitions(GenericWebApplicationContext context, |
||||
WebMergedContextConfiguration webMergedConfig); |
||||
|
||||
/** |
||||
* TODO [SPR-5243] Document customizeContext(). |
||||
*/ |
||||
protected void customizeContext(GenericWebApplicationContext context, WebMergedContextConfiguration webMergedConfig) { |
||||
} |
||||
|
||||
// --- ContextLoader -------------------------------------------------------
|
||||
|
||||
/** |
||||
* TODO [SPR-5243] Document overridden loadContext(String...). |
||||
* |
||||
* @see org.springframework.test.context.ContextLoader#loadContext(java.lang.String[]) |
||||
*/ |
||||
public final ApplicationContext loadContext(String... locations) throws Exception { |
||||
throw new UnsupportedOperationException( |
||||
"AbstractGenericWebContextLoader does not support the loadContext(String... locations) method"); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,118 @@
@@ -0,0 +1,118 @@
|
||||
/* |
||||
* Copyright 2002-2012 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. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.test.context.support; |
||||
|
||||
import java.lang.reflect.Modifier; |
||||
import java.util.ArrayList; |
||||
import java.util.List; |
||||
|
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.util.Assert; |
||||
|
||||
/** |
||||
* TODO [SPR-5243] Document AnnotationConfigContextLoaderUtils. |
||||
* |
||||
* @author Sam Brannen |
||||
* @since 3.2 |
||||
*/ |
||||
abstract class AnnotationConfigContextLoaderUtils { |
||||
|
||||
private static final Log logger = LogFactory.getLog(AnnotationConfigContextLoaderUtils.class); |
||||
|
||||
|
||||
private AnnotationConfigContextLoaderUtils() { |
||||
/* no-op */ |
||||
} |
||||
|
||||
private static boolean isStaticNonPrivateAndNonFinal(Class<?> clazz) { |
||||
Assert.notNull(clazz, "Class must not be null"); |
||||
int modifiers = clazz.getModifiers(); |
||||
return (Modifier.isStatic(modifiers) && !Modifier.isPrivate(modifiers) && !Modifier.isFinal(modifiers)); |
||||
} |
||||
|
||||
/** |
||||
* Determine if the supplied {@link Class} meets the criteria for being |
||||
* considered a <em>default configuration class</em> candidate. |
||||
* |
||||
* <p>Specifically, such candidates: |
||||
* |
||||
* <ul> |
||||
* <li>must not be <code>null</code></li> |
||||
* <li>must not be <code>private</code></li> |
||||
* <li>must not be <code>final</code></li> |
||||
* <li>must be <code>static</code></li> |
||||
* <li>must be annotated with {@code @Configuration}</li> |
||||
* </ul> |
||||
* |
||||
* @param clazz the class to check |
||||
* @return <code>true</code> if the supplied class meets the candidate criteria |
||||
*/ |
||||
private static boolean isDefaultConfigurationClassCandidate(Class<?> clazz) { |
||||
return clazz != null && isStaticNonPrivateAndNonFinal(clazz) && clazz.isAnnotationPresent(Configuration.class); |
||||
} |
||||
|
||||
/** |
||||
* Detect the default configuration classes for the supplied test class. |
||||
* |
||||
* <p>The returned class array will contain all static inner classes of |
||||
* the supplied class that meet the requirements for {@code @Configuration} |
||||
* class implementations as specified in the documentation for |
||||
* {@link Configuration @Configuration}. |
||||
* |
||||
* <p>The implementation of this method adheres to the contract defined in the |
||||
* {@link org.springframework.test.context.SmartContextLoader SmartContextLoader} |
||||
* SPI. Specifically, this method uses introspection to detect default |
||||
* configuration classes that comply with the constraints required of |
||||
* {@code @Configuration} class implementations. If a potential candidate |
||||
* configuration class does not meet these requirements, this method will log a |
||||
* warning, and the potential candidate class will be ignored. |
||||
* @param declaringClass the test class that declared {@code @ContextConfiguration} |
||||
* @return an array of default configuration classes, potentially empty but |
||||
* never <code>null</code> |
||||
*/ |
||||
static Class<?>[] detectDefaultConfigurationClasses(Class<?> declaringClass) { |
||||
Assert.notNull(declaringClass, "Declaring class must not be null"); |
||||
|
||||
List<Class<?>> configClasses = new ArrayList<Class<?>>(); |
||||
|
||||
for (Class<?> candidate : declaringClass.getDeclaredClasses()) { |
||||
if (isDefaultConfigurationClassCandidate(candidate)) { |
||||
configClasses.add(candidate); |
||||
} else { |
||||
if (logger.isDebugEnabled()) { |
||||
logger.debug(String.format( |
||||
"Ignoring class [%s]; it must be static, non-private, non-final, and annotated " |
||||
+ "with @Configuration to be considered a default configuration class.", |
||||
candidate.getName())); |
||||
} |
||||
} |
||||
} |
||||
|
||||
if (configClasses.isEmpty()) { |
||||
if (logger.isInfoEnabled()) { |
||||
logger.info(String.format("Could not detect default configuration classes for test class [%s]: " |
||||
+ "%s does not declare any static, non-private, non-final, inner classes " |
||||
+ "annotated with @Configuration.", declaringClass.getName(), declaringClass.getSimpleName())); |
||||
} |
||||
} |
||||
|
||||
return configClasses.toArray(new Class<?>[configClasses.size()]); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,151 @@
@@ -0,0 +1,151 @@
|
||||
/* |
||||
* Copyright 2002-2012 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. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.test.context.support; |
||||
|
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
import org.springframework.context.annotation.AnnotatedBeanDefinitionReader; |
||||
import org.springframework.test.context.ContextConfigurationAttributes; |
||||
import org.springframework.test.context.web.WebMergedContextConfiguration; |
||||
import org.springframework.util.ObjectUtils; |
||||
import org.springframework.web.context.support.GenericWebApplicationContext; |
||||
|
||||
/** |
||||
* TODO [SPR-5243] Document AnnotationConfigWebContextLoader. |
||||
* |
||||
* @author Sam Brannen |
||||
* @since 3.2 |
||||
*/ |
||||
public class AnnotationConfigWebContextLoader extends AbstractGenericWebContextLoader { |
||||
|
||||
private static final Log logger = LogFactory.getLog(AnnotationConfigWebContextLoader.class); |
||||
|
||||
|
||||
// --- SmartContextLoader -----------------------------------------------
|
||||
|
||||
/** |
||||
* Process <em>annotated classes</em> in the supplied {@link ContextConfigurationAttributes}. |
||||
* |
||||
* <p>If the <em>annotated classes</em> are <code>null</code> or empty and |
||||
* {@link #isGenerateDefaultLocations()} returns <code>true</code>, this |
||||
* <code>SmartContextLoader</code> will attempt to {@link |
||||
* #detectDefaultConfigurationClasses detect default configuration classes}. |
||||
* If defaults are detected they will be |
||||
* {@link ContextConfigurationAttributes#setClasses(Class[]) set} in the |
||||
* supplied configuration attributes. Otherwise, properties in the supplied |
||||
* configuration attributes will not be modified. |
||||
* |
||||
* @param configAttributes the context configuration attributes to process |
||||
* @see org.springframework.test.context.SmartContextLoader#processContextConfiguration(ContextConfigurationAttributes) |
||||
* @see #isGenerateDefaultLocations() |
||||
* @see #detectDefaultConfigurationClasses(Class) |
||||
*/ |
||||
public void processContextConfiguration(ContextConfigurationAttributes configAttributes) { |
||||
if (ObjectUtils.isEmpty(configAttributes.getClasses()) && isGenerateDefaultLocations()) { |
||||
Class<?>[] defaultConfigClasses = detectDefaultConfigurationClasses(configAttributes.getDeclaringClass()); |
||||
configAttributes.setClasses(defaultConfigClasses); |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* Detect the default configuration classes for the supplied test class. |
||||
* |
||||
* <p>The default implementation simply delegates to |
||||
* {@link AnnotationConfigContextLoaderUtils#detectDefaultConfigurationClasses(Class)}. |
||||
* |
||||
* @param declaringClass the test class that declared {@code @ContextConfiguration} |
||||
* @return an array of default configuration classes, potentially empty but |
||||
* never <code>null</code> |
||||
* @see AnnotationConfigContextLoaderUtils |
||||
*/ |
||||
protected Class<?>[] detectDefaultConfigurationClasses(Class<?> declaringClass) { |
||||
return AnnotationConfigContextLoaderUtils.detectDefaultConfigurationClasses(declaringClass); |
||||
} |
||||
|
||||
// --- AbstractContextLoader -----------------------------------------------
|
||||
|
||||
/** |
||||
* {@code AnnotationConfigWebContextLoader} should be used as a |
||||
* {@link org.springframework.test.context.SmartContextLoader SmartContextLoader}, |
||||
* not as a legacy {@link org.springframework.test.context.ContextLoader ContextLoader}. |
||||
* Consequently, this method is not supported. |
||||
* |
||||
* @see AbstractContextLoader#modifyLocations |
||||
* @throws UnsupportedOperationException |
||||
*/ |
||||
@Override |
||||
protected String[] modifyLocations(Class<?> clazz, String... locations) { |
||||
throw new UnsupportedOperationException( |
||||
"AnnotationConfigWebContextLoader does not support the modifyLocations(Class, String...) method"); |
||||
} |
||||
|
||||
/** |
||||
* {@code AnnotationConfigWebContextLoader} should be used as a |
||||
* {@link org.springframework.test.context.SmartContextLoader SmartContextLoader}, |
||||
* not as a legacy {@link org.springframework.test.context.ContextLoader ContextLoader}. |
||||
* Consequently, this method is not supported. |
||||
* |
||||
* @see AbstractContextLoader#generateDefaultLocations |
||||
* @throws UnsupportedOperationException |
||||
*/ |
||||
@Override |
||||
protected String[] generateDefaultLocations(Class<?> clazz) { |
||||
throw new UnsupportedOperationException( |
||||
"AnnotationConfigWebContextLoader does not support the generateDefaultLocations(Class) method"); |
||||
} |
||||
|
||||
/** |
||||
* {@code AnnotationConfigWebContextLoader} should be used as a |
||||
* {@link org.springframework.test.context.SmartContextLoader SmartContextLoader}, |
||||
* not as a legacy {@link org.springframework.test.context.ContextLoader ContextLoader}. |
||||
* Consequently, this method is not supported. |
||||
* |
||||
* @see AbstractContextLoader#getResourceSuffix |
||||
* @throws UnsupportedOperationException |
||||
*/ |
||||
@Override |
||||
protected String getResourceSuffix() { |
||||
throw new UnsupportedOperationException( |
||||
"AnnotationConfigWebContextLoader does not support the getResourceSuffix() method"); |
||||
} |
||||
|
||||
// --- AbstractGenericWebContextLoader -------------------------------------
|
||||
|
||||
/** |
||||
* Register classes in the supplied {@link GenericWebApplicationContext context} |
||||
* from the classes in the supplied {@link WebMergedContextConfiguration}. |
||||
* |
||||
* <p>Each class must represent an <em>annotated class</em>. An |
||||
* {@link AnnotatedBeanDefinitionReader} is used to register the appropriate |
||||
* bean definitions. |
||||
* |
||||
* @param context the context in which the annotated classes should be registered |
||||
* @param webMergedConfig the merged configuration from which the classes should be retrieved |
||||
* |
||||
* @see AbstractGenericWebContextLoader#loadBeanDefinitions |
||||
*/ |
||||
@Override |
||||
protected void loadBeanDefinitions(GenericWebApplicationContext context, |
||||
WebMergedContextConfiguration webMergedConfig) { |
||||
Class<?>[] annotatedClasses = webMergedConfig.getClasses(); |
||||
if (logger.isDebugEnabled()) { |
||||
logger.debug("Registering annotated classes: " + ObjectUtils.nullSafeToString(annotatedClasses)); |
||||
} |
||||
new AnnotatedBeanDefinitionReader(context).register(annotatedClasses); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,47 @@
@@ -0,0 +1,47 @@
|
||||
/* |
||||
* Copyright 2002-2012 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. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.test.context.support; |
||||
|
||||
import org.springframework.test.context.SmartContextLoader; |
||||
|
||||
/** |
||||
* {@code WebDelegatingSmartContextLoader} is a concrete implementation of |
||||
* {@link AbstractDelegatingSmartContextLoader} that delegates to an |
||||
* {@link XmlWebContextLoader} and an {@link AnnotationConfigWebContextLoader}. |
||||
* |
||||
* @author Sam Brannen |
||||
* @since 3.2 |
||||
* @see SmartContextLoader |
||||
* @see AbstractDelegatingSmartContextLoader |
||||
* @see XmlWebContextLoader |
||||
* @see AnnotationConfigWebContextLoader |
||||
*/ |
||||
public class WebDelegatingSmartContextLoader extends AbstractDelegatingSmartContextLoader { |
||||
|
||||
private final SmartContextLoader xmlLoader = new XmlWebContextLoader(); |
||||
private final SmartContextLoader annotationConfigLoader = new AnnotationConfigWebContextLoader(); |
||||
|
||||
|
||||
protected SmartContextLoader getXmlLoader() { |
||||
return this.xmlLoader; |
||||
} |
||||
|
||||
protected SmartContextLoader getAnnotationConfigLoader() { |
||||
return this.annotationConfigLoader; |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,49 @@
@@ -0,0 +1,49 @@
|
||||
/* |
||||
* Copyright 2002-2012 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. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.test.context.support; |
||||
|
||||
import org.springframework.beans.factory.xml.XmlBeanDefinitionReader; |
||||
import org.springframework.test.context.web.WebMergedContextConfiguration; |
||||
import org.springframework.web.context.support.GenericWebApplicationContext; |
||||
|
||||
/** |
||||
* TODO [SPR-5243] Document XmlWebContextLoader. |
||||
* |
||||
* @author Sam Brannen |
||||
* @since 3.2 |
||||
*/ |
||||
public class XmlWebContextLoader extends AbstractGenericWebContextLoader { |
||||
|
||||
/** |
||||
* Returns "<code>-context.xml</code>". |
||||
*/ |
||||
protected String getResourceSuffix() { |
||||
return "-context.xml"; |
||||
} |
||||
|
||||
/** |
||||
* TODO [SPR-5243] Document overridden loadBeanDefinitions(). |
||||
* |
||||
* @see org.springframework.test.context.support.AbstractGenericWebContextLoader#loadBeanDefinitions(org.springframework.web.context.support.GenericWebApplicationContext, org.springframework.test.context.web.WebMergedContextConfiguration) |
||||
*/ |
||||
@Override |
||||
protected void loadBeanDefinitions(GenericWebApplicationContext context, |
||||
WebMergedContextConfiguration webMergedConfig) { |
||||
new XmlBeanDefinitionReader(context).loadBeanDefinitions(webMergedConfig.getLocations()); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,45 @@
@@ -0,0 +1,45 @@
|
||||
/* |
||||
* Copyright 2002-2012 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. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.test.context.web; |
||||
|
||||
import java.lang.annotation.Documented; |
||||
import java.lang.annotation.ElementType; |
||||
import java.lang.annotation.Inherited; |
||||
import java.lang.annotation.Retention; |
||||
import java.lang.annotation.RetentionPolicy; |
||||
import java.lang.annotation.Target; |
||||
|
||||
/** |
||||
* TODO [SPR-5243] Document WebAppConfiguration. |
||||
* |
||||
* @author Sam Brannen |
||||
* @since 3.2 |
||||
*/ |
||||
@Documented |
||||
@Inherited |
||||
@Retention(RetentionPolicy.RUNTIME) |
||||
@Target(ElementType.TYPE) |
||||
public @interface WebAppConfiguration { |
||||
|
||||
/** |
||||
* The root directory of the web application (i.e., WAR); should not end with a slash. |
||||
* |
||||
* <p>Defaults to {@code "src/main/webapp"}. |
||||
*/ |
||||
String value() default "src/main/webapp"; |
||||
|
||||
} |
||||
@ -0,0 +1,122 @@
@@ -0,0 +1,122 @@
|
||||
/* |
||||
* Copyright 2002-2012 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. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.test.context.web; |
||||
|
||||
import java.util.Set; |
||||
|
||||
import org.springframework.context.ApplicationContextInitializer; |
||||
import org.springframework.context.ConfigurableApplicationContext; |
||||
import org.springframework.core.style.ToStringCreator; |
||||
import org.springframework.test.context.ContextLoader; |
||||
import org.springframework.test.context.MergedContextConfiguration; |
||||
import org.springframework.util.ObjectUtils; |
||||
import org.springframework.util.StringUtils; |
||||
|
||||
/** |
||||
* TODO [SPR-5243] Document WebMergedContextConfiguration. |
||||
* |
||||
* @author Sam Brannen |
||||
* @since 3.2 |
||||
*/ |
||||
public class WebMergedContextConfiguration extends MergedContextConfiguration { |
||||
|
||||
private static final long serialVersionUID = 7323361588604247458L; |
||||
|
||||
private final String resourceBasePath; |
||||
|
||||
|
||||
/** |
||||
* TODO [SPR-5243] Document WebMergedContextConfiguration constructor. |
||||
*/ |
||||
public WebMergedContextConfiguration( |
||||
Class<?> testClass, |
||||
String[] locations, |
||||
Class<?>[] classes, |
||||
Set<Class<? extends ApplicationContextInitializer<? extends ConfigurableApplicationContext>>> contextInitializerClasses, |
||||
String[] activeProfiles, String resourceBasePath, ContextLoader contextLoader) { |
||||
|
||||
super(testClass, locations, classes, contextInitializerClasses, activeProfiles, contextLoader); |
||||
|
||||
this.resourceBasePath = !StringUtils.hasText(resourceBasePath) ? "" : resourceBasePath; |
||||
} |
||||
|
||||
/** |
||||
* TODO [SPR-5243] Document getResourceBasePath(). |
||||
*/ |
||||
public String getResourceBasePath() { |
||||
return this.resourceBasePath; |
||||
} |
||||
|
||||
/** |
||||
* Generate a unique hash code for all properties of this |
||||
* {@code WebMergedContextConfiguration} excluding the |
||||
* {@linkplain #getTestClass() test class}. |
||||
*/ |
||||
@Override |
||||
public int hashCode() { |
||||
final int prime = 31; |
||||
int result = super.hashCode(); |
||||
result = prime * result + resourceBasePath.hashCode(); |
||||
return result; |
||||
} |
||||
|
||||
/** |
||||
* Determine if the supplied object is equal to this {@code WebMergedContextConfiguration} |
||||
* instance by comparing both object's {@linkplain #getLocations() locations}, |
||||
* {@linkplain #getClasses() annotated classes}, |
||||
* {@linkplain #getContextInitializerClasses() context initializer classes}, |
||||
* {@linkplain #getActiveProfiles() active profiles}, |
||||
* {@linkplain #getResourceBasePath() resource base path}, and the fully |
||||
* qualified names of their {@link #getContextLoader() ContextLoaders}. |
||||
*/ |
||||
@Override |
||||
public boolean equals(Object obj) { |
||||
|
||||
if (this == obj) { |
||||
return true; |
||||
} |
||||
if (!(obj instanceof WebMergedContextConfiguration)) { |
||||
return false; |
||||
} |
||||
|
||||
final WebMergedContextConfiguration that = (WebMergedContextConfiguration) obj; |
||||
|
||||
return super.equals(that) && this.getResourceBasePath().equals(that.getResourceBasePath()); |
||||
} |
||||
|
||||
/** |
||||
* Provide a String representation of the {@linkplain #getTestClass() test class}, |
||||
* {@linkplain #getLocations() locations}, {@linkplain #getClasses() annotated classes}, |
||||
* {@linkplain #getContextInitializerClasses() context initializer classes}, |
||||
* {@linkplain #getActiveProfiles() active profiles}, |
||||
* {@linkplain #getResourceBasePath() resource base path}, and the name of the |
||||
* {@link #getContextLoader() ContextLoader}. |
||||
*/ |
||||
@Override |
||||
public String toString() { |
||||
return new ToStringCreator(this)//
|
||||
.append("testClass", getTestClass())//
|
||||
.append("locations", ObjectUtils.nullSafeToString(getLocations()))//
|
||||
.append("classes", ObjectUtils.nullSafeToString(getClasses()))//
|
||||
.append("contextInitializerClasses", ObjectUtils.nullSafeToString(getContextInitializerClasses()))//
|
||||
.append("activeProfiles", ObjectUtils.nullSafeToString(getActiveProfiles()))//
|
||||
.append("resourceBasePath", getResourceBasePath())//
|
||||
.append("contextLoader", nullSafeToString(getContextLoader()))//
|
||||
.toString(); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,122 @@
@@ -0,0 +1,122 @@
|
||||
/* |
||||
* Copyright 2002-2012 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. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.test.context.web; |
||||
|
||||
import javax.servlet.ServletContext; |
||||
|
||||
import org.apache.commons.logging.Log; |
||||
import org.apache.commons.logging.LogFactory; |
||||
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; |
||||
import org.springframework.context.ApplicationContext; |
||||
import org.springframework.context.ConfigurableApplicationContext; |
||||
import org.springframework.mock.web.MockHttpServletRequest; |
||||
import org.springframework.mock.web.MockHttpServletResponse; |
||||
import org.springframework.mock.web.MockServletContext; |
||||
import org.springframework.test.context.TestContext; |
||||
import org.springframework.test.context.support.AbstractTestExecutionListener; |
||||
import org.springframework.web.context.WebApplicationContext; |
||||
import org.springframework.web.context.request.RequestContextHolder; |
||||
import org.springframework.web.context.request.ServletWebRequest; |
||||
|
||||
/** |
||||
* TODO [SPR-5243] Document WebTestExecutionListener. |
||||
* |
||||
* @author Sam Brannen |
||||
* @since 3.2 |
||||
*/ |
||||
public class WebTestExecutionListener extends AbstractTestExecutionListener { |
||||
|
||||
private static final Log logger = LogFactory.getLog(WebTestExecutionListener.class); |
||||
|
||||
|
||||
/** |
||||
* TODO [SPR-5243] Document overridden prepareTestInstance(). |
||||
* |
||||
* @see org.springframework.test.context.support.AbstractTestExecutionListener#prepareTestInstance(org.springframework.test.context.TestContext) |
||||
*/ |
||||
@Override |
||||
public void prepareTestInstance(TestContext testContext) throws Exception { |
||||
setUpRequestContextIfNecessary(testContext); |
||||
} |
||||
|
||||
/** |
||||
* TODO [SPR-5243] Document overridden beforeTestMethod(). |
||||
* |
||||
* @see org.springframework.test.context.support.AbstractTestExecutionListener#beforeTestMethod(org.springframework.test.context.TestContext) |
||||
*/ |
||||
@Override |
||||
public void beforeTestMethod(TestContext testContext) throws Exception { |
||||
setUpRequestContextIfNecessary(testContext); |
||||
} |
||||
|
||||
/** |
||||
* TODO [SPR-5243] Document setUpRequestContext(). |
||||
* |
||||
* @param testContext |
||||
* @param servletContext |
||||
*/ |
||||
private void setUpRequestContextIfNecessary(TestContext testContext) { |
||||
|
||||
ApplicationContext context = testContext.getApplicationContext(); |
||||
|
||||
if (context instanceof WebApplicationContext) { |
||||
WebApplicationContext wac = (WebApplicationContext) context; |
||||
ServletContext servletContext = wac.getServletContext(); |
||||
if (!(servletContext instanceof MockServletContext)) { |
||||
throw new IllegalStateException(String.format( |
||||
"The WebApplicationContext for test context %s must be configured with a MockServletContext.", |
||||
testContext)); |
||||
} |
||||
|
||||
if (logger.isDebugEnabled()) { |
||||
logger.debug(String.format( |
||||
"Setting up MockHttpServletRequest, MockHttpServletResponse, ServletWebRequest, and RequestContextHolder for test context %s.", |
||||
testContext)); |
||||
} |
||||
|
||||
if (RequestContextHolder.getRequestAttributes() == null) { |
||||
MockServletContext mockServletContext = (MockServletContext) servletContext; |
||||
MockHttpServletRequest request = new MockHttpServletRequest(mockServletContext); |
||||
MockHttpServletResponse response = new MockHttpServletResponse(); |
||||
ServletWebRequest servletWebRequest = new ServletWebRequest(request, response); |
||||
|
||||
RequestContextHolder.setRequestAttributes(servletWebRequest); |
||||
|
||||
if (wac instanceof ConfigurableApplicationContext) { |
||||
ConfigurableApplicationContext configurableApplicationContext = (ConfigurableApplicationContext) wac; |
||||
ConfigurableListableBeanFactory bf = configurableApplicationContext.getBeanFactory(); |
||||
bf.registerResolvableDependency(MockHttpServletResponse.class, response); |
||||
bf.registerResolvableDependency(ServletWebRequest.class, servletWebRequest); |
||||
} |
||||
} |
||||
} |
||||
} |
||||
|
||||
/** |
||||
* TODO [SPR-5243] Document overridden afterTestMethod(). |
||||
* |
||||
* @see org.springframework.test.context.support.AbstractTestExecutionListener#afterTestMethod(org.springframework.test.context.TestContext) |
||||
*/ |
||||
@Override |
||||
public void afterTestMethod(TestContext testContext) throws Exception { |
||||
if (logger.isDebugEnabled()) { |
||||
logger.debug(String.format("Resetting RequestContextHolder for test context %s.", testContext)); |
||||
} |
||||
RequestContextHolder.resetRequestAttributes(); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,92 @@
@@ -0,0 +1,92 @@
|
||||
/* |
||||
* Copyright 2002-2012 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. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.test.context.web; |
||||
|
||||
import static org.junit.Assert.*; |
||||
|
||||
import java.io.File; |
||||
|
||||
import javax.servlet.ServletContext; |
||||
|
||||
import org.junit.Test; |
||||
import org.junit.runner.RunWith; |
||||
import org.springframework.beans.factory.annotation.Autowired; |
||||
import org.springframework.mock.web.MockHttpServletRequest; |
||||
import org.springframework.mock.web.MockHttpServletResponse; |
||||
import org.springframework.mock.web.MockServletContext; |
||||
import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; |
||||
import org.springframework.web.context.ServletContextAware; |
||||
import org.springframework.web.context.WebApplicationContext; |
||||
import org.springframework.web.context.request.ServletWebRequest; |
||||
|
||||
/** |
||||
* @author Sam Brannen |
||||
* @since 3.2 |
||||
*/ |
||||
@RunWith(SpringJUnit4ClassRunner.class) |
||||
@WebAppConfiguration |
||||
public abstract class AbstractBasicWacTests implements ServletContextAware { |
||||
|
||||
protected ServletContext servletContext; |
||||
|
||||
@Autowired |
||||
protected WebApplicationContext wac; |
||||
|
||||
@Autowired |
||||
protected MockServletContext mockServletContext; |
||||
|
||||
@Autowired |
||||
protected MockHttpServletRequest request; |
||||
|
||||
@Autowired |
||||
protected MockHttpServletResponse response; |
||||
|
||||
@Autowired |
||||
protected ServletWebRequest webRequest; |
||||
|
||||
@Autowired |
||||
protected String foo; |
||||
|
||||
|
||||
public void setServletContext(ServletContext servletContext) { |
||||
this.servletContext = servletContext; |
||||
} |
||||
|
||||
@Test |
||||
public void basicWacFeatures() throws Exception { |
||||
assertNotNull("ServletContext should be set in the WAC.", wac.getServletContext()); |
||||
|
||||
assertNotNull("ServletContext should have been set via ServletContextAware.", servletContext); |
||||
|
||||
assertNotNull("ServletContext should have been autowired from the WAC.", mockServletContext); |
||||
assertNotNull("MockHttpServletRequest should have been autowired from the WAC.", request); |
||||
assertNotNull("MockHttpServletResponse should have been autowired from the WAC.", response); |
||||
assertNotNull("ServletWebRequest should have been autowired from the WAC.", webRequest); |
||||
|
||||
Object rootWac = mockServletContext.getAttribute(WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE); |
||||
assertNotNull("Root WAC must be stored in the ServletContext as: " |
||||
+ WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE, rootWac); |
||||
assertSame("test WAC and Root WAC in ServletContext must be the same object.", wac, rootWac); |
||||
assertSame("ServletContext instances must be the same object.", mockServletContext, wac.getServletContext()); |
||||
assertSame("ServletContext in the WAC and in the mock request", mockServletContext, request.getServletContext()); |
||||
|
||||
assertEquals("Getting real path for ServletContext resource.", |
||||
new File("src/main/webapp/index.jsp").getCanonicalPath(), mockServletContext.getRealPath("index.jsp")); |
||||
|
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,48 @@
@@ -0,0 +1,48 @@
|
||||
/* |
||||
* Copyright 2002-2012 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. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.test.context.web; |
||||
|
||||
import static org.junit.Assert.*; |
||||
|
||||
import org.junit.Test; |
||||
import org.springframework.context.annotation.Bean; |
||||
import org.springframework.context.annotation.Configuration; |
||||
import org.springframework.test.context.ContextConfiguration; |
||||
|
||||
/** |
||||
* @author Sam Brannen |
||||
* @since 3.2 |
||||
*/ |
||||
@ContextConfiguration |
||||
public class BasicAnnotationConfigWacTests extends AbstractBasicWacTests { |
||||
|
||||
@Configuration |
||||
static class Config { |
||||
|
||||
@Bean |
||||
public String foo() { |
||||
return "enigma"; |
||||
} |
||||
} |
||||
|
||||
|
||||
@Test |
||||
public void fooEnigmaAutowired() { |
||||
assertEquals("enigma", foo); |
||||
} |
||||
|
||||
} |
||||
@ -0,0 +1,40 @@
@@ -0,0 +1,40 @@
|
||||
/* |
||||
* Copyright 2002-2012 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. |
||||
* You may obtain a copy of the License at |
||||
* |
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
* |
||||
* Unless required by applicable law or agreed to in writing, software |
||||
* distributed under the License is distributed on an "AS IS" BASIS, |
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
||||
* See the License for the specific language governing permissions and |
||||
* limitations under the License. |
||||
*/ |
||||
|
||||
package org.springframework.test.context.web; |
||||
|
||||
import org.junit.runner.RunWith; |
||||
import org.junit.runners.Suite; |
||||
import org.junit.runners.Suite.SuiteClasses; |
||||
import org.springframework.test.context.ContextLoader; |
||||
import org.springframework.web.context.WebApplicationContext; |
||||
|
||||
/** |
||||
* Convenience test suite for integration tests that verify support for |
||||
* {@link WebApplicationContext} {@linkplain ContextLoader context loaders} |
||||
* in the TestContext framework. |
||||
* |
||||
* @author Sam Brannen |
||||
* @since 3.2 |
||||
*/ |
||||
@RunWith(Suite.class) |
||||
// Note: the following 'multi-line' layout is for enhanced code readability.
|
||||
@SuiteClasses({//
|
||||
BasicXmlWacTests.class,//
|
||||
BasicAnnotationConfigWacTests.class //
|
||||
}) |
||||
public class WebContextLoaderTestSuite { |
||||
} |
||||
@ -0,0 +1,7 @@
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?> |
||||
<beans xmlns="http://www.springframework.org/schema/beans" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" |
||||
xmlns:c="http://www.springframework.org/schema/c" xsi:schemaLocation="http://www.springframework.org/schema/beans http://www.springframework.org/schema/beans/spring-beans.xsd"> |
||||
|
||||
<bean id="foo" class="java.lang.String" c:_="bar" /> |
||||
|
||||
</beans> |
||||
Loading…
Reference in new issue