001/* 002 * Copyright 2002-2013 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.web.context.support; 018 019import javax.servlet.ServletConfig; 020import javax.servlet.ServletContext; 021 022import org.springframework.beans.factory.config.ConfigurableListableBeanFactory; 023import org.springframework.context.support.AbstractRefreshableConfigApplicationContext; 024import org.springframework.core.env.ConfigurableEnvironment; 025import org.springframework.core.io.Resource; 026import org.springframework.core.io.support.ResourcePatternResolver; 027import org.springframework.ui.context.Theme; 028import org.springframework.ui.context.ThemeSource; 029import org.springframework.ui.context.support.UiApplicationContextUtils; 030import org.springframework.web.context.ConfigurableWebApplicationContext; 031import org.springframework.web.context.ConfigurableWebEnvironment; 032import org.springframework.web.context.ServletConfigAware; 033import org.springframework.web.context.ServletContextAware; 034 035/** 036 * {@link org.springframework.context.support.AbstractRefreshableApplicationContext} 037 * subclass which implements the 038 * {@link org.springframework.web.context.ConfigurableWebApplicationContext} 039 * interface for web environments. Provides a "configLocations" property, 040 * to be populated through the ConfigurableWebApplicationContext interface 041 * on web application startup. 042 * 043 * <p>This class is as easy to subclass as AbstractRefreshableApplicationContext: 044 * All you need to implements is the {@link #loadBeanDefinitions} method; 045 * see the superclass javadoc for details. Note that implementations are supposed 046 * to load bean definitions from the files specified by the locations returned 047 * by the {@link #getConfigLocations} method. 048 * 049 * <p>Interprets resource paths as servlet context resources, i.e. as paths beneath 050 * the web application root. Absolute paths, e.g. for files outside the web app root, 051 * can be accessed via "file:" URLs, as implemented by 052 * {@link org.springframework.core.io.DefaultResourceLoader}. 053 * 054 * <p>In addition to the special beans detected by 055 * {@link org.springframework.context.support.AbstractApplicationContext}, 056 * this class detects a bean of type {@link org.springframework.ui.context.ThemeSource} 057 * in the context, under the special bean name "themeSource". 058 * 059 * <p><b>This is the web context to be subclassed for a different bean definition format.</b> 060 * Such a context implementation can be specified as "contextClass" context-param 061 * for {@link org.springframework.web.context.ContextLoader} or as "contextClass" 062 * init-param for {@link org.springframework.web.servlet.FrameworkServlet}, 063 * replacing the default {@link XmlWebApplicationContext}. It will then automatically 064 * receive the "contextConfigLocation" context-param or init-param, respectively. 065 * 066 * <p>Note that WebApplicationContext implementations are generally supposed 067 * to configure themselves based on the configuration received through the 068 * {@link ConfigurableWebApplicationContext} interface. In contrast, a standalone 069 * application context might allow for configuration in custom startup code 070 * (for example, {@link org.springframework.context.support.GenericApplicationContext}). 071 * 072 * @author Juergen Hoeller 073 * @since 1.1.3 074 * @see #loadBeanDefinitions 075 * @see org.springframework.web.context.ConfigurableWebApplicationContext#setConfigLocations 076 * @see org.springframework.ui.context.ThemeSource 077 * @see XmlWebApplicationContext 078 */ 079public abstract class AbstractRefreshableWebApplicationContext extends AbstractRefreshableConfigApplicationContext 080 implements ConfigurableWebApplicationContext, ThemeSource { 081 082 /** Servlet context that this context runs in */ 083 private ServletContext servletContext; 084 085 /** Servlet config that this context runs in, if any */ 086 private ServletConfig servletConfig; 087 088 /** Namespace of this context, or {@code null} if root */ 089 private String namespace; 090 091 /** the ThemeSource for this ApplicationContext */ 092 private ThemeSource themeSource; 093 094 095 public AbstractRefreshableWebApplicationContext() { 096 setDisplayName("Root WebApplicationContext"); 097 } 098 099 100 @Override 101 public void setServletContext(ServletContext servletContext) { 102 this.servletContext = servletContext; 103 } 104 105 @Override 106 public ServletContext getServletContext() { 107 return this.servletContext; 108 } 109 110 @Override 111 public void setServletConfig(ServletConfig servletConfig) { 112 this.servletConfig = servletConfig; 113 if (servletConfig != null && this.servletContext == null) { 114 setServletContext(servletConfig.getServletContext()); 115 } 116 } 117 118 @Override 119 public ServletConfig getServletConfig() { 120 return this.servletConfig; 121 } 122 123 @Override 124 public void setNamespace(String namespace) { 125 this.namespace = namespace; 126 if (namespace != null) { 127 setDisplayName("WebApplicationContext for namespace '" + namespace + "'"); 128 } 129 } 130 131 @Override 132 public String getNamespace() { 133 return this.namespace; 134 } 135 136 @Override 137 public String[] getConfigLocations() { 138 return super.getConfigLocations(); 139 } 140 141 @Override 142 public String getApplicationName() { 143 return (this.servletContext != null ? this.servletContext.getContextPath() : ""); 144 } 145 146 /** 147 * Create and return a new {@link StandardServletEnvironment}. Subclasses may override 148 * in order to configure the environment or specialize the environment type returned. 149 */ 150 @Override 151 protected ConfigurableEnvironment createEnvironment() { 152 return new StandardServletEnvironment(); 153 } 154 155 /** 156 * Register request/session scopes, a {@link ServletContextAwareProcessor}, etc. 157 */ 158 @Override 159 protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) { 160 beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig)); 161 beanFactory.ignoreDependencyInterface(ServletContextAware.class); 162 beanFactory.ignoreDependencyInterface(ServletConfigAware.class); 163 164 WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext); 165 WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig); 166 } 167 168 /** 169 * This implementation supports file paths beneath the root of the ServletContext. 170 * @see ServletContextResource 171 */ 172 @Override 173 protected Resource getResourceByPath(String path) { 174 return new ServletContextResource(this.servletContext, path); 175 } 176 177 /** 178 * This implementation supports pattern matching in unexpanded WARs too. 179 * @see ServletContextResourcePatternResolver 180 */ 181 @Override 182 protected ResourcePatternResolver getResourcePatternResolver() { 183 return new ServletContextResourcePatternResolver(this); 184 } 185 186 /** 187 * Initialize the theme capability. 188 */ 189 @Override 190 protected void onRefresh() { 191 this.themeSource = UiApplicationContextUtils.initThemeSource(this); 192 } 193 194 /** 195 * {@inheritDoc} 196 * <p>Replace {@code Servlet}-related property sources. 197 */ 198 @Override 199 protected void initPropertySources() { 200 ConfigurableEnvironment env = getEnvironment(); 201 if (env instanceof ConfigurableWebEnvironment) { 202 ((ConfigurableWebEnvironment) env).initPropertySources(this.servletContext, this.servletConfig); 203 } 204 } 205 206 @Override 207 public Theme getTheme(String themeName) { 208 return this.themeSource.getTheme(themeName); 209 } 210 211}