001    /**
002     * Copyright (c) 2000-present Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.spring.context;
016    
017    import com.liferay.portal.bean.BeanLocatorImpl;
018    import com.liferay.portal.kernel.bean.BeanLocator;
019    import com.liferay.portal.kernel.bean.PortletBeanLocatorUtil;
020    import com.liferay.portal.kernel.configuration.ConfigurationFactoryUtil;
021    import com.liferay.portal.kernel.log.Log;
022    import com.liferay.portal.kernel.log.LogFactoryUtil;
023    import com.liferay.portal.kernel.portlet.PortletClassLoaderUtil;
024    import com.liferay.portal.kernel.util.MethodCache;
025    import com.liferay.portal.util.PropsValues;
026    
027    import java.lang.reflect.Method;
028    
029    import javax.servlet.ServletContext;
030    import javax.servlet.ServletContextEvent;
031    
032    import org.springframework.context.ApplicationContext;
033    import org.springframework.context.ConfigurableApplicationContext;
034    import org.springframework.context.support.ClassPathXmlApplicationContext;
035    import org.springframework.web.context.ConfigurableWebApplicationContext;
036    import org.springframework.web.context.ContextLoaderListener;
037    import org.springframework.web.context.WebApplicationContext;
038    import org.springframework.web.context.support.WebApplicationContextUtils;
039    
040    /**
041     * @author Brian Wing Shun Chan
042     * @see    PortletApplicationContext
043     */
044    public class PortletContextLoaderListener extends ContextLoaderListener {
045    
046            @Override
047            public void contextDestroyed(ServletContextEvent servletContextEvent) {
048                    ClassLoader classLoader = PortletClassLoaderUtil.getClassLoader();
049    
050                    ServletContext servletContext = servletContextEvent.getServletContext();
051    
052                    try {
053                            Class<?> beanLocatorUtilClass = Class.forName(
054                                    "com.liferay.util.bean.PortletBeanLocatorUtil", true,
055                                    classLoader);
056    
057                            Method setBeanLocatorMethod = beanLocatorUtilClass.getMethod(
058                                    "setBeanLocator", new Class[] {BeanLocator.class});
059    
060                            setBeanLocatorMethod.invoke(
061                                    beanLocatorUtilClass, new Object[] {null});
062    
063                            PortletBeanLocatorUtil.setBeanLocator(
064                                    servletContext.getServletContextName(), null);
065                    }
066                    catch (Exception e) {
067                            if (_log.isWarnEnabled()) {
068                                    _log.warn(e, e);
069                            }
070                    }
071    
072                    super.contextDestroyed(servletContextEvent);
073    
074                    Object parentApplicationContext = servletContext.getAttribute(
075                            _PARENT_APPLICATION_CONTEXT_KEY);
076    
077                    if (parentApplicationContext instanceof
078                                    ConfigurableApplicationContext) {
079    
080                            servletContext.removeAttribute(_PARENT_APPLICATION_CONTEXT_KEY);
081    
082                            ConfigurableApplicationContext configurableApplicationContext =
083                                    (ConfigurableApplicationContext)parentApplicationContext;
084    
085                            configurableApplicationContext.close();
086                    }
087            }
088    
089            @Override
090            public void contextInitialized(ServletContextEvent servletContextEvent) {
091                    MethodCache.reset();
092    
093                    ServletContext servletContext = servletContextEvent.getServletContext();
094    
095                    Object previousApplicationContext = servletContext.getAttribute(
096                            WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
097    
098                    servletContext.removeAttribute(
099                            WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
100    
101                    ClassLoader classLoader = PortletClassLoaderUtil.getClassLoader();
102    
103                    super.contextInitialized(servletContextEvent);
104    
105                    PortletBeanFactoryCleaner.readBeans();
106    
107                    ApplicationContext applicationContext =
108                            WebApplicationContextUtils.getWebApplicationContext(servletContext);
109    
110                    BeanLocatorImpl beanLocatorImpl = new BeanLocatorImpl(
111                            classLoader, applicationContext);
112    
113                    beanLocatorImpl.setPACLServletContextName(
114                            servletContext.getServletContextName());
115    
116                    try {
117                            Class<?> beanLocatorUtilClass = Class.forName(
118                                    "com.liferay.util.bean.PortletBeanLocatorUtil", true,
119                                    classLoader);
120    
121                            Method setBeanLocatorMethod = beanLocatorUtilClass.getMethod(
122                                    "setBeanLocator", new Class[] {BeanLocator.class});
123    
124                            setBeanLocatorMethod.invoke(
125                                    beanLocatorUtilClass, new Object[] {beanLocatorImpl});
126    
127                            PortletBeanLocatorUtil.setBeanLocator(
128                                    servletContext.getServletContextName(), beanLocatorImpl);
129                    }
130                    catch (Exception e) {
131                            _log.error(e, e);
132                    }
133    
134                    if (previousApplicationContext == null) {
135                            servletContext.removeAttribute(
136                                    WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE);
137                    }
138                    else {
139                            servletContext.setAttribute(
140                                    WebApplicationContext.ROOT_WEB_APPLICATION_CONTEXT_ATTRIBUTE,
141                                    previousApplicationContext);
142                    }
143            }
144    
145            @Override
146            protected void customizeContext(
147                    ServletContext servletContext,
148                    ConfigurableWebApplicationContext configurableWebApplicationContext) {
149    
150                    String configLocation = servletContext.getInitParameter(
151                            _PORTAL_CONFIG_LOCATION_PARAM);
152    
153                    configurableWebApplicationContext.setConfigLocation(configLocation);
154    
155                    configurableWebApplicationContext.addBeanFactoryPostProcessor(
156                            new PortletBeanFactoryPostProcessor());
157            }
158    
159            @Override
160            protected Class<?> determineContextClass(ServletContext servletContext) {
161                    return PortletApplicationContext.class;
162            }
163    
164            @Override
165            protected ApplicationContext loadParentContext(
166                    ServletContext servletContext) {
167    
168                    try {
169                            ConfigurationFactoryUtil.getConfiguration(
170                                    PortletClassLoaderUtil.getClassLoader(), "service");
171                    }
172                    catch (Exception e) {
173                            return null;
174                    }
175    
176                    ApplicationContext applicationContext =
177                            new ClassPathXmlApplicationContext(
178                                    PropsValues.SPRING_PORTLET_CONFIGS, true);
179    
180                    servletContext.setAttribute(
181                            _PARENT_APPLICATION_CONTEXT_KEY, applicationContext);
182    
183                    return applicationContext;
184            }
185    
186            private static final String _PARENT_APPLICATION_CONTEXT_KEY =
187                    PortletContextLoaderListener.class.getName() +
188                            "#parentApplicationContext";
189    
190            private static final String _PORTAL_CONFIG_LOCATION_PARAM =
191                    "portalContextConfigLocation";
192    
193            private static final Log _log = LogFactoryUtil.getLog(
194                    PortletContextLoaderListener.class);
195    
196    }