001/*
002 * Copyright 2002-2012 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.portlet.context;
018
019import javax.portlet.PortletConfig;
020import javax.portlet.PortletContext;
021import javax.servlet.ServletContext;
022
023import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
024import org.springframework.beans.factory.support.DefaultListableBeanFactory;
025import org.springframework.context.ApplicationContext;
026import org.springframework.context.support.AbstractRefreshableConfigApplicationContext;
027import org.springframework.core.env.ConfigurableEnvironment;
028import org.springframework.core.io.Resource;
029import org.springframework.core.io.support.ResourcePatternResolver;
030import org.springframework.web.context.ServletContextAware;
031import org.springframework.web.context.WebApplicationContext;
032import org.springframework.web.context.support.ServletContextAwareProcessor;
033
034/**
035 * {@link org.springframework.context.support.AbstractRefreshableApplicationContext}
036 * subclass which implements the {@link ConfigurablePortletApplicationContext}
037 * interface for portlet environments. Provides a "configLocations" property,
038 * to be populated through the ConfigurablePortletApplicationContext interface
039 * on portlet application startup.
040 *
041 * <p>This class is as easy to subclass as AbstractRefreshableApplicationContext:
042 * All you need to implements is the {@link #loadBeanDefinitions} method;
043 * see the superclass javadoc for details. Note that implementations are supposed
044 * to load bean definitions from the files specified by the locations returned
045 * by the {@link #getConfigLocations} method.
046 *
047 * <p>Interprets resource paths as servlet context resources, i.e. as paths beneath
048 * the web application root. Absolute paths, e.g. for files outside the web app root,
049 * can be accessed via "file:" URLs, as implemented by
050 * {@link org.springframework.core.io.DefaultResourceLoader}.
051 *
052 * <p><b>This is the portlet context to be subclassed for a different bean definition format.</b>
053 * Such a context implementation can be specified as "contextClass" init-param
054 * for FrameworkPortlet, replacing the default {@link XmlPortletApplicationContext}.
055 * It will then automatically receive the "contextConfigLocation" init-param.
056 *
057 * <p>Note that Portlet-based context implementations are generally supposed
058 * to configure themselves based on the configuration received through the
059 * {@link ConfigurablePortletApplicationContext} interface. In contrast, a standalone
060 * application context might allow for configuration in custom startup code
061 * (for example, {@link org.springframework.context.support.GenericApplicationContext}).
062 *
063 * @author Juergen Hoeller
064 * @author John A. Lewis
065 * @since 2.0
066 * @see #loadBeanDefinitions
067 * @see org.springframework.web.portlet.context.ConfigurablePortletApplicationContext#setConfigLocations
068 * @see XmlPortletApplicationContext
069 */
070public abstract class AbstractRefreshablePortletApplicationContext extends AbstractRefreshableConfigApplicationContext
071                implements WebApplicationContext, ConfigurablePortletApplicationContext {
072
073        /** Servlet context that this context runs in */
074        private ServletContext servletContext;
075
076        /** Portlet context that this context runs in */
077        private PortletContext portletContext;
078
079        /** Portlet config that this context runs in */
080        private PortletConfig portletConfig;
081
082        /** Namespace of this context, or null if root */
083        private String namespace;
084
085
086        public AbstractRefreshablePortletApplicationContext() {
087                setDisplayName("Root PortletApplicationContext");
088        }
089
090        /**
091         * {@inheritDoc}
092         * <p>The parent {@linkplain #getEnvironment() environment} is
093         * delegated to this (child) context if the parent is a
094         * {@link org.springframework.context.ConfigurableApplicationContext} implementation.
095         * <p>The parent {@linkplain #getServletContext() servlet context} is
096         * delegated to this (child) context if the parent is a {@link WebApplicationContext}
097         * implementation.
098         */
099        @Override
100        public void setParent(ApplicationContext parent) {
101                super.setParent(parent);
102                if (parent instanceof WebApplicationContext) {
103                        this.servletContext = ((WebApplicationContext) parent).getServletContext();
104                }
105        }
106
107        @Override
108        public ServletContext getServletContext() {
109                return this.servletContext;
110        }
111
112        @Override
113        public void setPortletContext(PortletContext portletContext) {
114                this.portletContext = portletContext;
115        }
116
117        @Override
118        public PortletContext getPortletContext() {
119                return this.portletContext;
120        }
121
122        @Override
123        public void setPortletConfig(PortletConfig portletConfig) {
124                this.portletConfig = portletConfig;
125                if (portletConfig != null && this.portletContext == null) {
126                        this.portletContext = portletConfig.getPortletContext();
127                }
128        }
129
130        @Override
131        public PortletConfig getPortletConfig() {
132                return this.portletConfig;
133        }
134
135        @Override
136        public void setNamespace(String namespace) {
137                this.namespace = namespace;
138                if (namespace != null) {
139                        setDisplayName("PortletApplicationContext for namespace '" + namespace + "'");
140                }
141        }
142
143        @Override
144        public String getNamespace() {
145                return this.namespace;
146        }
147
148        @Override
149        public String[] getConfigLocations() {
150                return super.getConfigLocations();
151        }
152
153        @Override
154        public String getApplicationName() {
155                if (this.portletContext == null) {
156                        return "";
157                }
158                String name = this.portletContext.getPortletContextName();
159                return (name != null ? name : "");
160        }
161
162        /**
163         * Create and return a new {@link StandardPortletEnvironment}.
164         */
165        @Override
166        protected ConfigurableEnvironment createEnvironment() {
167                return new StandardPortletEnvironment();
168        }
169
170        /**
171         * Register request/session scopes, a {@link PortletContextAwareProcessor}, etc.
172         */
173        @Override
174        protected void postProcessBeanFactory(ConfigurableListableBeanFactory beanFactory) {
175                beanFactory.addBeanPostProcessor(new ServletContextAwareProcessor(this.servletContext));
176                beanFactory.addBeanPostProcessor(new PortletContextAwareProcessor(this.portletContext, this.portletConfig));
177                beanFactory.ignoreDependencyInterface(ServletContextAware.class);
178                beanFactory.ignoreDependencyInterface(PortletContextAware.class);
179                beanFactory.ignoreDependencyInterface(PortletConfigAware.class);
180
181                PortletApplicationContextUtils.registerPortletApplicationScopes(beanFactory, this.portletContext);
182                PortletApplicationContextUtils.registerEnvironmentBeans(
183                                beanFactory, this.servletContext, this.portletContext, this.portletConfig);
184        }
185
186        /**
187         * This implementation supports file paths beneath the root of the PortletContext.
188         * @see PortletContextResource
189         */
190        @Override
191        protected Resource getResourceByPath(String path) {
192                return new PortletContextResource(this.portletContext, path);
193        }
194
195        /**
196         * This implementation supports pattern matching in unexpanded WARs too.
197         * @see PortletContextResourcePatternResolver
198         */
199        @Override
200        protected ResourcePatternResolver getResourcePatternResolver() {
201                return new PortletContextResourcePatternResolver(this);
202        }
203
204        @Override
205        protected void customizeBeanFactory(DefaultListableBeanFactory beanFactory) {
206                super.customizeBeanFactory(beanFactory);
207        }
208
209}