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}