/* * Copyright 2002-2018 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.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.support.AbstractContextLoader; import org.springframework.util.Assert; import org.springframework.web.context.WebApplicationContext; import org.springframework.web.context.support.GenericWebApplicationContext; /** * Abstract, generic extension of {@link AbstractContextLoader} that loads a * {@link GenericWebApplicationContext}. * *

If instances of concrete subclasses are invoked via the * {@link org.springframework.test.context.SmartContextLoader SmartContextLoader} * SPI, the context will be loaded from the {@link MergedContextConfiguration} * provided to {@link #loadContext(MergedContextConfiguration)}. In such cases, a * {@code SmartContextLoader} will decide whether to load the context from * locations or annotated classes. Note that {@code * AbstractGenericWebContextLoader} does not support the {@code * loadContext(String... locations)} method from the legacy * {@link org.springframework.test.context.ContextLoader ContextLoader} SPI. * *

Concrete subclasses must provide an appropriate implementation of * {@link #loadBeanDefinitions}. * * @author Sam Brannen * @author Phillip Webb * @since 3.2 * @see #loadContext(MergedContextConfiguration) * @see #loadContext(String...) */ public abstract class AbstractGenericWebContextLoader extends AbstractContextLoader { protected static final Log logger = LogFactory.getLog(AbstractGenericWebContextLoader.class); // SmartContextLoader /** * Load a Spring {@link WebApplicationContext} from the supplied * {@link MergedContextConfiguration}. *

Implementation details: *

* @return a new web application context * @see org.springframework.test.context.SmartContextLoader#loadContext(MergedContextConfiguration) * @see GenericWebApplicationContext */ @Override public final ConfigurableApplicationContext loadContext(MergedContextConfiguration mergedConfig) throws Exception { Assert.isTrue(mergedConfig instanceof WebMergedContextConfiguration, () -> 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)); } validateMergedContextConfiguration(webMergedConfig); GenericWebApplicationContext context = new GenericWebApplicationContext(); ApplicationContext parent = mergedConfig.getParentApplicationContext(); if (parent != null) { context.setParent(parent); } 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; } /** * Validate the supplied {@link WebMergedContextConfiguration} with respect to * what this context loader supports. *

The default implementation is a no-op but can be overridden by * subclasses as appropriate. * @param mergedConfig the merged configuration to validate * @throws IllegalStateException if the supplied configuration is not valid * for this context loader * @since 4.0.4 */ protected void validateMergedContextConfiguration(WebMergedContextConfiguration mergedConfig) { /* no-op */ } /** * Configures web resources for the supplied web application context (WAC). *

Implementation Details

*

If the supplied WAC has no parent or its parent is not a WAC, the * supplied WAC will be configured as the Root WAC (see "Root WAC * Configuration" below). *

Otherwise the context hierarchy of the supplied WAC will be traversed * to find the top-most WAC (i.e., the root); and the {@link ServletContext} * of the Root WAC will be set as the {@code ServletContext} for the supplied * WAC. *

Root WAC Configuration

*