001/*
002 * Copyright 2002-2017 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.StaticApplicationContext;
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.ServletConfigAware;
034import org.springframework.web.context.ServletContextAware;
035
036/**
037 * Static {@link org.springframework.web.context.WebApplicationContext}
038 * implementation for testing. Not intended for use in production applications.
039 *
040 * <p>Implements the {@link org.springframework.web.context.ConfigurableWebApplicationContext}
041 * interface to allow for direct replacement of an {@link XmlWebApplicationContext},
042 * despite not actually supporting external configuration files.
043 *
044 * <p>Interprets resource paths as servlet context resources, i.e. as paths beneath
045 * the web application root. Absolute paths, e.g. for files outside the web app root,
046 * can be accessed via "file:" URLs, as implemented by
047 * {@link org.springframework.core.io.DefaultResourceLoader}.
048 *
049 * <p>In addition to the special beans detected by
050 * {@link org.springframework.context.support.AbstractApplicationContext},
051 * this class detects a bean of type {@link org.springframework.ui.context.ThemeSource}
052 * in the context, under the special bean name "themeSource".
053 *
054 * @author Rod Johnson
055 * @author Juergen Hoeller
056 * @see org.springframework.ui.context.ThemeSource
057 */
058public class StaticWebApplicationContext extends StaticApplicationContext
059                implements ConfigurableWebApplicationContext, ThemeSource {
060
061        @Nullable
062        private ServletContext servletContext;
063
064        @Nullable
065        private ServletConfig servletConfig;
066
067        @Nullable
068        private String namespace;
069
070        @Nullable
071        private ThemeSource themeSource;
072
073
074        public StaticWebApplicationContext() {
075                setDisplayName("Root WebApplicationContext");
076        }
077
078
079        /**
080         * Set the ServletContext that this WebApplicationContext runs in.
081         */
082        @Override
083        public void setServletContext(@Nullable ServletContext servletContext) {
084                this.servletContext = servletContext;
085        }
086
087        @Override
088        @Nullable
089        public ServletContext getServletContext() {
090                return this.servletContext;
091        }
092
093        @Override
094        public void setServletConfig(@Nullable ServletConfig servletConfig) {
095                this.servletConfig = servletConfig;
096                if (servletConfig != null && this.servletContext == null) {
097                        this.servletContext = servletConfig.getServletContext();
098                }
099        }
100
101        @Override
102        @Nullable
103        public ServletConfig getServletConfig() {
104                return this.servletConfig;
105        }
106
107        @Override
108        public void setNamespace(@Nullable String namespace) {
109                this.namespace = namespace;
110                if (namespace != null) {
111                        setDisplayName("WebApplicationContext for namespace '" + namespace + "'");
112                }
113        }
114
115        @Override
116        @Nullable
117        public String getNamespace() {
118                return this.namespace;
119        }
120
121        /**
122         * The {@link StaticWebApplicationContext} class does not support this method.
123         * @throws UnsupportedOperationException <b>always</b>
124         */
125        @Override
126        public void setConfigLocation(String configLocation) {
127                throw new UnsupportedOperationException("StaticWebApplicationContext does not support config locations");
128        }
129
130        /**
131         * The {@link StaticWebApplicationContext} class does not support this method.
132         * @throws UnsupportedOperationException <b>always</b>
133         */
134        @Override
135        public void setConfigLocations(String... configLocations) {
136                throw new UnsupportedOperationException("StaticWebApplicationContext does not support config locations");
137        }
138
139        @Override
140        public String[] getConfigLocations() {
141                return null;
142        }
143
144
145        /**
146         * Register request/session scopes, a {@link ServletContextAwareProcessor}, etc.
147         */
148        @Override
149        protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
150                beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext, this.servletConfig));
151                beanFactory.ignoreDependencyInterface(ServletContextAware.class);
152                beanFactory.ignoreDependencyInterface(ServletConfigAware.class);
153
154                WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
155                WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext, this.servletConfig);
156        }
157
158        /**
159         * This implementation supports file paths beneath the root of the ServletContext.
160         * @see ServletContextResource
161         */
162        @Override
163        protected Resource getResourceByPath(String path) {
164                Assert.state(this.servletContext != null, "No ServletContext available");
165                return new ServletContextResource(this.servletContext, path);
166        }
167
168        /**
169         * This implementation supports pattern matching in unexpanded WARs too.
170         * @see ServletContextResourcePatternResolver
171         */
172        @Override
173        protected ResourcePatternResolver getResourcePatternResolver() {
174                return new ServletContextResourcePatternResolver(this);
175        }
176
177        /**
178         * Create and return a new {@link StandardServletEnvironment}.
179         */
180        @Override
181        protected ConfigurableEnvironment createEnvironment() {
182                return new StandardServletEnvironment();
183        }
184
185        /**
186         * Initialize the theme capability.
187         */
188        @Override
189        protected void onRefresh() {
190                this.themeSource = UiApplicationContextUtils.initThemeSource(this);
191        }
192
193        @Override
194        protected void initPropertySources() {
195                WebApplicationContextUtils.initServletPropertySources(getEnvironment().getPropertySources(),
196                                this.servletContext, this.servletConfig);
197        }
198
199        @Override
200        @Nullable
201        public Theme getTheme(String themeName) {
202                Assert.state(this.themeSource != null, "No ThemeSource available");
203                return this.themeSource.getTheme(themeName);
204        }
205
206}