001/*
002 * Copyright 2002-2014 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.beans.factory.support.DefaultListableBeanFactory;
024import org.springframework.context.support.GenericApplicationContext;
025import org.springframework.core.env.ConfigurableEnvironment;
026import org.springframework.core.io.Resource;
027import org.springframework.core.io.support.ResourcePatternResolver;
028import org.springframework.ui.context.Theme;
029import org.springframework.ui.context.ThemeSource;
030import org.springframework.ui.context.support.UiApplicationContextUtils;
031import org.springframework.util.ObjectUtils;
032import org.springframework.util.StringUtils;
033import org.springframework.web.context.ConfigurableWebApplicationContext;
034import org.springframework.web.context.ConfigurableWebEnvironment;
035import org.springframework.web.context.ServletContextAware;
036
037/**
038 * Subclass of {@link GenericApplicationContext}, suitable for web environments.
039 *
040 * <p>Implements the
041 * {@link org.springframework.web.context.ConfigurableWebApplicationContext},
042 * but is not intended for declarative setup in {@code web.xml}. Instead,
043 * it is designed for programmatic setup, for example for building nested contexts or
044 * for use within Spring 3.1 {@link org.springframework.web.WebApplicationInitializer}s.
045 *
046 * <p><b>If you intend to implement a WebApplicationContext that reads bean definitions
047 * from configuration files, consider deriving from AbstractRefreshableWebApplicationContext,
048 * reading the bean definitions in an implementation of the {@code loadBeanDefinitions}
049 * method.</b>
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 AbstractApplicationContext.
054 *
055 * <p>In addition to the special beans detected by
056 * {@link org.springframework.context.support.AbstractApplicationContext},
057 * this class detects a ThemeSource bean in the context, with the name "themeSource".
058 *
059 * @author Juergen Hoeller
060 * @author Chris Beams
061 * @since 1.2
062 */
063public class GenericWebApplicationContext extends GenericApplicationContext
064                implements ConfigurableWebApplicationContext, ThemeSource {
065
066        private ServletContext servletContext;
067
068        private ThemeSource themeSource;
069
070
071        /**
072         * Create a new GenericWebApplicationContext.
073         * @see #setServletContext
074         * @see #registerBeanDefinition
075         * @see #refresh
076         */
077        public GenericWebApplicationContext() {
078                super();
079        }
080
081        /**
082         * Create a new GenericWebApplicationContext for the given ServletContext.
083         * @param servletContext the ServletContext to run in
084         * @see #registerBeanDefinition
085         * @see #refresh
086         */
087        public GenericWebApplicationContext(ServletContext servletContext) {
088                this.servletContext = servletContext;
089        }
090
091        /**
092         * Create a new GenericWebApplicationContext with the given DefaultListableBeanFactory.
093         * @param beanFactory the DefaultListableBeanFactory instance to use for this context
094         * @see #setServletContext
095         * @see #registerBeanDefinition
096         * @see #refresh
097         */
098        public GenericWebApplicationContext(DefaultListableBeanFactory beanFactory) {
099                super(beanFactory);
100        }
101
102        /**
103         * Create a new GenericWebApplicationContext with the given DefaultListableBeanFactory.
104         * @param beanFactory the DefaultListableBeanFactory instance to use for this context
105         * @param servletContext the ServletContext to run in
106         * @see #registerBeanDefinition
107         * @see #refresh
108         */
109        public GenericWebApplicationContext(DefaultListableBeanFactory beanFactory, ServletContext servletContext) {
110                super(beanFactory);
111                this.servletContext = servletContext;
112        }
113
114
115        /**
116         * Set the ServletContext that this WebApplicationContext runs in.
117         */
118        @Override
119        public void setServletContext(ServletContext servletContext) {
120                this.servletContext = servletContext;
121        }
122
123        @Override
124        public ServletContext getServletContext() {
125                return this.servletContext;
126        }
127
128        @Override
129        public String getApplicationName() {
130                return (this.servletContext != null ? this.servletContext.getContextPath() : "");
131        }
132
133        /**
134         * Create and return a new {@link StandardServletEnvironment}.
135         */
136        @Override
137        protected ConfigurableEnvironment createEnvironment() {
138                return new StandardServletEnvironment();
139        }
140
141        /**
142         * Register ServletContextAwareProcessor.
143         * @see ServletContextAwareProcessor
144         */
145        @Override
146        protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
147                beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext));
148                beanFactory.ignoreDependencyInterface(ServletContextAware.class);
149
150                WebApplicationContextUtils.registerWebApplicationScopes(beanFactory, this.servletContext);
151                WebApplicationContextUtils.registerEnvironmentBeans(beanFactory, this.servletContext);
152        }
153
154        /**
155         * This implementation supports file paths beneath the root of the ServletContext.
156         * @see ServletContextResource
157         */
158        @Override
159        protected Resource getResourceByPath(String path) {
160                return new ServletContextResource(this.servletContext, path);
161        }
162
163        /**
164         * This implementation supports pattern matching in unexpanded WARs too.
165         * @see ServletContextResourcePatternResolver
166         */
167        @Override
168        protected ResourcePatternResolver getResourcePatternResolver() {
169                return new ServletContextResourcePatternResolver(this);
170        }
171
172        /**
173         * Initialize the theme capability.
174         */
175        @Override
176        protected void onRefresh() {
177                this.themeSource = UiApplicationContextUtils.initThemeSource(this);
178        }
179
180        /**
181         * {@inheritDoc}
182         * <p>Replace {@code Servlet}-related property sources.
183         */
184        @Override
185        protected void initPropertySources() {
186                ConfigurableEnvironment env = getEnvironment();
187                if (env instanceof ConfigurableWebEnvironment) {
188                        ((ConfigurableWebEnvironment) env).initPropertySources(this.servletContext, null);
189                }
190        }
191
192        @Override
193        public Theme getTheme(String themeName) {
194                return this.themeSource.getTheme(themeName);
195        }
196
197
198        // ---------------------------------------------------------------------
199        // Pseudo-implementation of ConfigurableWebApplicationContext
200        // ---------------------------------------------------------------------
201
202        @Override
203        public void setServletConfig(ServletConfig servletConfig) {
204                // no-op
205        }
206
207        @Override
208        public ServletConfig getServletConfig() {
209                throw new UnsupportedOperationException(
210                                "GenericWebApplicationContext does not support getServletConfig()");
211        }
212
213        @Override
214        public void setNamespace(String namespace) {
215                // no-op
216        }
217
218        @Override
219        public String getNamespace() {
220                throw new UnsupportedOperationException(
221                                "GenericWebApplicationContext does not support getNamespace()");
222        }
223
224        @Override
225        public void setConfigLocation(String configLocation) {
226                if (StringUtils.hasText(configLocation)) {
227                        throw new UnsupportedOperationException(
228                                        "GenericWebApplicationContext does not support setConfigLocation(). " +
229                                        "Do you still have an 'contextConfigLocations' init-param set?");
230                }
231        }
232
233        @Override
234        public void setConfigLocations(String... configLocations) {
235                if (!ObjectUtils.isEmpty(configLocations)) {
236                        throw new UnsupportedOperationException(
237                                        "GenericWebApplicationContext does not support setConfigLocations(). " +
238                                        "Do you still have an 'contextConfigLocations' init-param set?");
239                }
240        }
241
242        @Override
243        public String[] getConfigLocations() {
244                throw new UnsupportedOperationException(
245                                "GenericWebApplicationContext does not support getConfigLocations()");
246        }
247
248}