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