/*
* 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.
* 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.servlet.setup;
import java.io.IOException;
import java.lang.annotation.Annotation;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import javax.servlet.ServletContext;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.BeansException;
import org.springframework.beans.TypeConverter;
import org.springframework.beans.factory.BeanFactory;
import org.springframework.beans.factory.NoSuchBeanDefinitionException;
import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
import org.springframework.beans.factory.config.DependencyDescriptor;
import org.springframework.beans.factory.config.NamedBeanHolder;
import org.springframework.beans.factory.support.StaticListableBeanFactory;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationContextAware;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.MessageSource;
import org.springframework.context.MessageSourceResolvable;
import org.springframework.context.NoSuchMessageException;
import org.springframework.context.support.DelegatingMessageSource;
import org.springframework.core.ResolvableType;
import org.springframework.core.env.Environment;
import org.springframework.core.env.StandardEnvironment;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.ResourcePatternResolver;
import org.springframework.util.ClassUtils;
import org.springframework.util.ObjectUtils;
import org.springframework.web.context.WebApplicationContext;
import org.springframework.web.context.support.ServletContextResourcePatternResolver;
/**
* A stub WebApplicationContext that accepts registrations of object instances.
*
* <p>As registered object instances are instantiated and initialized externally,
* there is no wiring, bean initialization, lifecycle events, as well as no
* pre-processing and post-processing hooks typically associated with beans
* managed by an {@link ApplicationContext}. Just a simple lookup into a
* {@link StaticListableBeanFactory}.
*
* @author Rossen Stoyanchev
* @author Juergen Hoeller
* @since 3.2
*/
class StubWebApplicationContext implements WebApplicationContext {
private final ServletContext servletContext;
private final StubBeanFactory beanFactory = new StubBeanFactory();
private final String id = ObjectUtils.identityToString(this);
private final String displayName = ObjectUtils.identityToString(this);
private final long startupDate = System.currentTimeMillis();
private final Environment environment = new StandardEnvironment();
private final MessageSource messageSource = new DelegatingMessageSource();
private final ResourcePatternResolver resourcePatternResolver;
public StubWebApplicationContext(ServletContext servletContext) {
this.servletContext = servletContext;
this.resourcePatternResolver = new ServletContextResourcePatternResolver(servletContext);
}
/**
* Returns an instance that can initialize {@link ApplicationContextAware} beans.
*/
@Override
public AutowireCapableBeanFactory getAutowireCapableBeanFactory() throws IllegalStateException {
return this.beanFactory;
}
@Override
public ServletContext getServletContext() {
return this.servletContext;
}
//---------------------------------------------------------------------
// Implementation of ApplicationContext interface
//---------------------------------------------------------------------
@Override
public String getId() {
return this.id;
}
@Override
public String getApplicationName() {
return "";
}
@Override
public String getDisplayName() {
return this.displayName;
}
@Override
public long getStartupDate() {
return this.startupDate;
}
@Override
public ApplicationContext getParent() {
return null;
}
@Override
public Environment getEnvironment() {
return this.environment ;
}
public void addBean(String name, Object bean) {
this.beanFactory.addBean(name, bean);
}
public void addBeans(List<?> beans) {
if (beans == null) {
return;
}
for (Object bean : beans) {
String name = bean.getClass().getName() + "#" + ObjectUtils.getIdentityHexString(bean);
this.beanFactory.addBean(name, bean);
}
}
//---------------------------------------------------------------------
// Implementation of BeanFactory interface
//---------------------------------------------------------------------
@Override
public Object getBean(String name) throws BeansException {
return this.beanFactory.getBean(name);
}
@Override
public <T> T getBean(String name, Class<T> requiredType) throws BeansException {
return this.beanFactory.getBean(name, requiredType);
}
@Override
public <T> T getBean(Class<T> requiredType) throws BeansException {
return this.beanFactory.getBean(requiredType);
}
@Override
public Object getBean(String name, Object... args) throws BeansException {
return this.beanFactory.getBean(name, args);
}
@Override
public <T> T getBean(Class<T> requiredType, Object... args) throws BeansException {
return this.beanFactory.getBean(requiredType, args);
}
@Override
public boolean containsBean(String name) {
return this.beanFactory.containsBean(name);
}
@Override
public boolean isSingleton(String name) throws NoSuchBeanDefinitionException {
return this.beanFactory.isSingleton(name);
}
@Override
public boolean isPrototype(String name) throws NoSuchBeanDefinitionException {
return this.beanFactory.isPrototype(name);
}
@Override
public boolean isTypeMatch(String name, ResolvableType typeToMatch) throws NoSuchBeanDefinitionException {
return this.beanFactory.isTypeMatch(name, typeToMatch);
}
@Override
public boolean isTypeMatch(String name, Class<?> typeToMatch) throws NoSuchBeanDefinitionException {
return this.beanFactory.isTypeMatch(name, typeToMatch);
}
@Override
public Class<?> getType(String name) throws NoSuchBeanDefinitionException {
return this.beanFactory.getType(name);
}
@Override
public String[] getAliases(String name) {
return this.beanFactory.getAliases(name);
}
//---------------------------------------------------------------------
// Implementation of ListableBeanFactory interface
//---------------------------------------------------------------------
@Override
public boolean containsBeanDefinition(String beanName) {
return this.beanFactory.containsBeanDefinition(beanName);
}
@Override
public int getBeanDefinitionCount() {
return this.beanFactory.getBeanDefinitionCount();
}
@Override
public String[] getBeanDefinitionNames() {
return this.beanFactory.getBeanDefinitionNames();
}
@Override
public String[] getBeanNamesForType(ResolvableType type) {
return this.beanFactory.getBeanNamesForType(type);
}
@Override
public String[] getBeanNamesForType(Class<?> type) {
return this.beanFactory.getBeanNamesForType(type);
}
@Override
public String[] getBeanNamesForType(Class<?> type, boolean includeNonSingletons, boolean allowEagerInit) {
return this.beanFactory.getBeanNamesForType(type, includeNonSingletons, allowEagerInit);
}
@Override
public <T> Map<String, T> getBeansOfType(Class<T> type) throws BeansException {
return this.beanFactory.getBeansOfType(type);
}
@Override
public <T> Map<String, T> getBeansOfType(Class<T> type, boolean includeNonSingletons, boolean allowEagerInit)
throws BeansException {
return this.beanFactory.getBeansOfType(type, includeNonSingletons, allowEagerInit);
}
@Override
public String[] getBeanNamesForAnnotation(Class<? extends Annotation> annotationType) {
return this.beanFactory.getBeanNamesForAnnotation(annotationType);
}
@Override
public Map<String, Object> getBeansWithAnnotation(Class<? extends Annotation> annotationType)
throws BeansException {
return this.beanFactory.getBeansWithAnnotation(annotationType);
}
@Override
public <A extends Annotation> A findAnnotationOnBean(String beanName, Class<A> annotationType)
throws NoSuchBeanDefinitionException{
return this.beanFactory.findAnnotationOnBean(beanName, annotationType);
}
//---------------------------------------------------------------------
// Implementation of HierarchicalBeanFactory interface
//---------------------------------------------------------------------
@Override
public BeanFactory getParentBeanFactory() {
return null;
}
@Override
public boolean containsLocalBean(String name) {
return this.beanFactory.containsBean(name);
}
//---------------------------------------------------------------------
// Implementation of MessageSource interface
//---------------------------------------------------------------------
@Override
public String getMessage(String code, Object args[], String defaultMessage, Locale locale) {
return this.messageSource.getMessage(code, args, defaultMessage, locale);
}
@Override
public String getMessage(String code, Object args[], Locale locale) throws NoSuchMessageException {
return this.messageSource.getMessage(code, args, locale);
}
@Override
public String getMessage(MessageSourceResolvable resolvable, Locale locale) throws NoSuchMessageException {
return this.messageSource.getMessage(resolvable, locale);
}
//---------------------------------------------------------------------
// Implementation of ResourceLoader interface
//---------------------------------------------------------------------
@Override
public ClassLoader getClassLoader() {
return ClassUtils.getDefaultClassLoader();
}
@Override
public Resource getResource(String location) {
return this.resourcePatternResolver.getResource(location);
}
//---------------------------------------------------------------------
// Other
//---------------------------------------------------------------------
@Override
public void publishEvent(ApplicationEvent event) {
}
@Override
public void publishEvent(Object event) {
}
@Override
public Resource[] getResources(String locationPattern) throws IOException {
return this.resourcePatternResolver.getResources(locationPattern);
}
/**
* An extension of StaticListableBeanFactory that implements
* AutowireCapableBeanFactory in order to allow bean initialization of
* {@link ApplicationContextAware} singletons.
*/
private class StubBeanFactory extends StaticListableBeanFactory implements AutowireCapableBeanFactory {
@Override
public Object initializeBean(Object existingBean, String beanName) throws BeansException {
if (existingBean instanceof ApplicationContextAware) {
((ApplicationContextAware) existingBean).setApplicationContext(StubWebApplicationContext.this);
}
return existingBean;
}
@Override
public <T> T createBean(Class<T> beanClass) {
return BeanUtils.instantiateClass(beanClass);
}
@Override
public Object createBean(Class<?> beanClass, int autowireMode, boolean dependencyCheck) {
return BeanUtils.instantiateClass(beanClass);
}
@Override
public Object autowire(Class<?> beanClass, int autowireMode, boolean dependencyCheck) {
return BeanUtils.instantiateClass(beanClass);
}
@Override
public void autowireBean(Object existingBean) throws BeansException {
}
@Override
public void autowireBeanProperties(Object existingBean, int autowireMode, boolean dependencyCheck) {
}
@Override
public Object configureBean(Object existingBean, String beanName) {
return existingBean;
}
@Override
public <T> NamedBeanHolder<T> resolveNamedBean(Class<T> requiredType) throws BeansException {
throw new UnsupportedOperationException("Dependency resolution not supported");
}
@Override
public Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName) {
throw new UnsupportedOperationException("Dependency resolution not supported");
}
@Override
public Object resolveDependency(DependencyDescriptor descriptor, String requestingBeanName,
Set<String> autowiredBeanNames, TypeConverter typeConverter) {
throw new UnsupportedOperationException("Dependency resolution not supported");
}
@Override
public void applyBeanPropertyValues(Object existingBean, String beanName) throws BeansException {
}
@Override
public Object applyBeanPostProcessorsBeforeInitialization(Object existingBean, String beanName) {
return existingBean;
}
@Override
public Object applyBeanPostProcessorsAfterInitialization(Object existingBean, String beanName) {
return existingBean;
}
@Override
public void destroyBean(Object existingBean) {
}
}
}