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.dao.orm.hibernate.FieldInterceptionHelperUtil;
019    import com.liferay.portal.deploy.hot.CustomJspBagRegistryUtil;
020    import com.liferay.portal.deploy.hot.ServiceWrapperRegistry;
021    import com.liferay.portal.kernel.bean.PortalBeanLocatorUtil;
022    import com.liferay.portal.kernel.cache.CacheRegistryUtil;
023    import com.liferay.portal.kernel.cache.MultiVMPoolUtil;
024    import com.liferay.portal.kernel.cache.SingleVMPoolUtil;
025    import com.liferay.portal.kernel.cache.thread.local.ThreadLocalCacheManager;
026    import com.liferay.portal.kernel.dao.db.DBManagerUtil;
027    import com.liferay.portal.kernel.deploy.DeployManagerUtil;
028    import com.liferay.portal.kernel.deploy.hot.HotDeployUtil;
029    import com.liferay.portal.kernel.exception.LoggedExceptionInInitializerError;
030    import com.liferay.portal.kernel.executor.PortalExecutorManager;
031    import com.liferay.portal.kernel.log.Log;
032    import com.liferay.portal.kernel.log.LogFactoryUtil;
033    import com.liferay.portal.kernel.messaging.MessageBus;
034    import com.liferay.portal.kernel.messaging.sender.SingleDestinationMessageSenderFactory;
035    import com.liferay.portal.kernel.portlet.PortletBagPool;
036    import com.liferay.portal.kernel.process.ClassPathUtil;
037    import com.liferay.portal.kernel.scheduler.SchedulerEngineHelper;
038    import com.liferay.portal.kernel.servlet.DirectServletRegistryUtil;
039    import com.liferay.portal.kernel.servlet.SerializableSessionAttributeListener;
040    import com.liferay.portal.kernel.servlet.ServletContextPool;
041    import com.liferay.portal.kernel.template.TemplateResourceLoaderUtil;
042    import com.liferay.portal.kernel.util.CharPool;
043    import com.liferay.portal.kernel.util.ClassLoaderPool;
044    import com.liferay.portal.kernel.util.ClassLoaderUtil;
045    import com.liferay.portal.kernel.util.ClearThreadLocalUtil;
046    import com.liferay.portal.kernel.util.ClearTimerThreadUtil;
047    import com.liferay.portal.kernel.util.InstancePool;
048    import com.liferay.portal.kernel.util.JavaConstants;
049    import com.liferay.portal.kernel.util.MethodCache;
050    import com.liferay.portal.kernel.util.PortalLifecycleUtil;
051    import com.liferay.portal.kernel.util.PropsKeys;
052    import com.liferay.portal.kernel.util.ReferenceRegistry;
053    import com.liferay.portal.kernel.util.ReflectionUtil;
054    import com.liferay.portal.kernel.util.ServerDetector;
055    import com.liferay.portal.kernel.util.StringPool;
056    import com.liferay.portal.kernel.util.StringUtil;
057    import com.liferay.portal.kernel.util.SystemProperties;
058    import com.liferay.portal.kernel.util.Validator;
059    import com.liferay.portal.module.framework.ModuleFrameworkUtilAdapter;
060    import com.liferay.portal.security.lang.SecurityManagerUtil;
061    import com.liferay.portal.spring.aop.DynamicProxyCreator;
062    import com.liferay.portal.spring.bean.BeanReferenceRefreshUtil;
063    import com.liferay.portal.util.InitUtil;
064    import com.liferay.portal.util.PropsValues;
065    import com.liferay.portal.util.WebAppPool;
066    import com.liferay.portlet.PortletContextBagPool;
067    import com.liferay.registry.dependency.ServiceDependencyListener;
068    import com.liferay.registry.dependency.ServiceDependencyManager;
069    
070    import java.beans.PropertyDescriptor;
071    
072    import java.io.Closeable;
073    import java.io.File;
074    import java.io.IOException;
075    
076    import java.lang.reflect.Field;
077    
078    import java.util.Map;
079    
080    import javax.servlet.ServletContext;
081    import javax.servlet.ServletContextEvent;
082    
083    import javax.sql.DataSource;
084    
085    import org.springframework.beans.CachedIntrospectionResults;
086    import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
087    import org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory;
088    import org.springframework.context.ApplicationContext;
089    import org.springframework.web.context.ContextLoader;
090    import org.springframework.web.context.ContextLoaderListener;
091    
092    /**
093     * @author Michael Young
094     * @author Shuyang Zhou
095     * @author Raymond Augé
096     */
097    public class PortalContextLoaderListener extends ContextLoaderListener {
098    
099            public static String getPortalServletContextName() {
100                    return _portalServletContextName;
101            }
102    
103            public static String getPortalServletContextPath() {
104                    return _portalServletContextPath;
105            }
106    
107            @Override
108            public void contextDestroyed(ServletContextEvent servletContextEvent) {
109                    PortalContextLoaderLifecycleThreadLocal.setDestroying(true);
110    
111                    ThreadLocalCacheManager.destroy();
112    
113                    if (_serviceWrapperRegistry != null) {
114                            _serviceWrapperRegistry.close();
115                    }
116    
117                    try {
118                            ClearThreadLocalUtil.clearThreadLocal();
119                    }
120                    catch (Exception e) {
121                            _log.error(e, e);
122                    }
123    
124                    try {
125                            ClearTimerThreadUtil.clearTimerThread();
126                    }
127                    catch (Exception e) {
128                            _log.error(e, e);
129                    }
130    
131                    try {
132                            DirectServletRegistryUtil.clearServlets();
133                    }
134                    catch (Exception e) {
135                            _log.error(e, e);
136                    }
137    
138                    try {
139                            HotDeployUtil.reset();
140                    }
141                    catch (Exception e) {
142                            _log.error(e, e);
143                    }
144    
145                    try {
146                            ModuleFrameworkUtilAdapter.stopRuntime();
147                    }
148                    catch (Exception e) {
149                            _log.error(e, e);
150                    }
151    
152                    try {
153                            PortalLifecycleUtil.reset();
154                    }
155                    catch (Exception e) {
156                            _log.error(e, e);
157                    }
158    
159                    closeDataSource("counterDataSourceImpl");
160    
161                    closeDataSource("liferayDataSourceImpl");
162    
163                    try {
164                            super.contextDestroyed(servletContextEvent);
165    
166                            try {
167                                    ModuleFrameworkUtilAdapter.stopFramework(
168                                            PropsValues.MODULE_FRAMEWORK_STOP_WAIT_TIMEOUT);
169                            }
170                            catch (Exception e) {
171                                    _log.error(e, e);
172                            }
173    
174                            _arrayApplicationContext.close();
175                    }
176                    finally {
177                            PortalContextLoaderLifecycleThreadLocal.setDestroying(false);
178    
179                            SecurityManagerUtil.destroy();
180                    }
181            }
182    
183            @Override
184            public void contextInitialized(ServletContextEvent servletContextEvent) {
185                    Thread currentThread = Thread.currentThread();
186    
187                    SystemProperties.load(currentThread.getContextClassLoader());
188    
189                    DBManagerUtil.reset();
190                    DeployManagerUtil.reset();
191                    InstancePool.reset();
192                    MethodCache.reset();
193                    PortalBeanLocatorUtil.reset();
194                    PortletBagPool.reset();
195    
196                    ReferenceRegistry.releaseReferences();
197    
198                    FieldInterceptionHelperUtil.initialize();
199    
200                    final ServletContext servletContext =
201                            servletContextEvent.getServletContext();
202    
203                    String portalLibDir = servletContext.getRealPath("/WEB-INF/lib");
204    
205                    portalLibDir = StringUtil.replace(
206                            portalLibDir, CharPool.BACK_SLASH, CharPool.FORWARD_SLASH);
207    
208                    if (Validator.isNotNull(portalLibDir)) {
209                            SystemProperties.set(
210                                    PropsKeys.LIFERAY_LIB_PORTAL_DIR, portalLibDir);
211                    }
212    
213                    InitUtil.init();
214    
215                    _portalServletContextName = servletContext.getServletContextName();
216    
217                    if (_portalServletContextName == null) {
218                            _portalServletContextName = StringPool.BLANK;
219                    }
220    
221                    if (ServerDetector.isJetty() &&
222                            _portalServletContextName.equals(StringPool.SLASH)) {
223    
224                            _portalServletContextName = StringPool.BLANK;
225                    }
226    
227                    _portalServletContextPath = servletContext.getContextPath();
228    
229                    if (ServerDetector.isWebSphere() &&
230                            _portalServletContextPath.isEmpty()) {
231    
232                            _portalServletContextName = StringPool.BLANK;
233                    }
234    
235                    ClassPathUtil.initializeClassPaths(servletContext);
236    
237                    File tempDir = (File)servletContext.getAttribute(
238                            JavaConstants.JAVAX_SERVLET_CONTEXT_TEMPDIR);
239    
240                    PropsValues.LIFERAY_WEB_PORTAL_CONTEXT_TEMPDIR =
241                            tempDir.getAbsolutePath();
242    
243                    try {
244                            ModuleFrameworkUtilAdapter.initFramework();
245    
246                            _arrayApplicationContext = new ArrayApplicationContext(
247                                    PropsValues.SPRING_INFRASTRUCTURE_CONFIGS);
248    
249                            servletContext.setAttribute(
250                                    PortalApplicationContext.PARENT_APPLICATION_CONTEXT,
251                                    _arrayApplicationContext);
252    
253                            ModuleFrameworkUtilAdapter.registerContext(
254                                    _arrayApplicationContext);
255    
256                            ModuleFrameworkUtilAdapter.startFramework();
257                    }
258                    catch (Exception e) {
259                            throw new RuntimeException(e);
260                    }
261    
262                    ServiceDependencyManager serviceDependencyManager =
263                            new ServiceDependencyManager();
264    
265                    serviceDependencyManager.addServiceDependencyListener(
266                            new ServiceDependencyListener() {
267    
268                                    @Override
269                                    public void destroy() {
270                                    }
271    
272                                    @Override
273                                    public void dependenciesFulfilled() {
274                                            _serviceWrapperRegistry = new ServiceWrapperRegistry();
275                                    }
276    
277                            });
278    
279                    serviceDependencyManager.registerDependencies(
280                            MessageBus.class, PortalExecutorManager.class,
281                            SchedulerEngineHelper.class,
282                            SingleDestinationMessageSenderFactory.class);
283    
284                    ClassLoader portalClassLoader = ClassLoaderUtil.getPortalClassLoader();
285    
286                    ClassLoaderPool.register(_portalServletContextName, portalClassLoader);
287    
288                    PortalContextLoaderLifecycleThreadLocal.setInitializing(true);
289    
290                    try {
291                            super.contextInitialized(servletContextEvent);
292                    }
293                    finally {
294                            PortalContextLoaderLifecycleThreadLocal.setInitializing(false);
295                    }
296    
297                    ApplicationContext applicationContext =
298                            ContextLoader.getCurrentWebApplicationContext();
299    
300                    try {
301                            BeanReferenceRefreshUtil.refresh(
302                                    applicationContext.getAutowireCapableBeanFactory());
303                    }
304                    catch (Exception e) {
305                            _log.error(e, e);
306                    }
307    
308                    if (PropsValues.CACHE_CLEAR_ON_CONTEXT_INITIALIZATION) {
309                            CacheRegistryUtil.clear();
310                            PortletContextBagPool.clear();
311                            WebAppPool.clear();
312    
313                            TemplateResourceLoaderUtil.clearCache();
314    
315                            ServletContextPool.clear();
316    
317                            MultiVMPoolUtil.clear();
318                            SingleVMPoolUtil.clear();
319                    }
320    
321                    ServletContextPool.put(_portalServletContextName, servletContext);
322    
323                    BeanLocatorImpl beanLocatorImpl = new BeanLocatorImpl(
324                            portalClassLoader, applicationContext);
325    
326                    PortalBeanLocatorUtil.setBeanLocator(beanLocatorImpl);
327    
328                    ClassLoader classLoader = portalClassLoader;
329    
330                    while (classLoader != null) {
331                            CachedIntrospectionResults.clearClassLoader(classLoader);
332    
333                            classLoader = classLoader.getParent();
334                    }
335    
336                    AutowireCapableBeanFactory autowireCapableBeanFactory =
337                            applicationContext.getAutowireCapableBeanFactory();
338    
339                    clearFilteredPropertyDescriptorsCache(autowireCapableBeanFactory);
340    
341                    DynamicProxyCreator dynamicProxyCreator =
342                            DynamicProxyCreator.getDynamicProxyCreator();
343    
344                    dynamicProxyCreator.clear();
345    
346                    try {
347                            ModuleFrameworkUtilAdapter.registerContext(applicationContext);
348    
349                            ModuleFrameworkUtilAdapter.startRuntime();
350                    }
351                    catch (Exception e) {
352                            throw new RuntimeException(e);
353                    }
354    
355                    CustomJspBagRegistryUtil.getCustomJspBags();
356    
357                    initListeners(servletContext);
358            }
359    
360            protected void clearFilteredPropertyDescriptorsCache(
361                    AutowireCapableBeanFactory autowireCapableBeanFactory) {
362    
363                    try {
364                            Map<Class<?>, PropertyDescriptor[]>
365                                    filteredPropertyDescriptorsCache =
366                                            (Map<Class<?>, PropertyDescriptor[]>)
367                                                    _FILTERED_PROPERTY_DESCRIPTORS_CACHE_FIELD.get(
368                                                            autowireCapableBeanFactory);
369    
370                            filteredPropertyDescriptorsCache.clear();
371                    }
372                    catch (Exception e) {
373                            _log.error(e, e);
374                    }
375            }
376    
377            protected void closeDataSource(String name) {
378                    DataSource dataSource = (DataSource)PortalBeanLocatorUtil.locate(name);
379    
380                    if (dataSource instanceof Closeable) {
381                            try {
382                                    Closeable closeable = (Closeable)dataSource;
383    
384                                    closeable.close();
385                            }
386                            catch (IOException ioe) {
387                                    _log.error(ioe, ioe);
388                            }
389                    }
390            }
391    
392            protected void initListeners(ServletContext servletContext) {
393                    if (PropsValues.SESSION_VERIFY_SERIALIZABLE_ATTRIBUTE) {
394                            servletContext.addListener(
395                                    SerializableSessionAttributeListener.class);
396                    }
397            }
398    
399            private static final Field _FILTERED_PROPERTY_DESCRIPTORS_CACHE_FIELD;
400    
401            private static final Log _log = LogFactoryUtil.getLog(
402                    PortalContextLoaderListener.class);
403    
404            private static String _portalServletContextName = StringPool.BLANK;
405            private static String _portalServletContextPath = StringPool.SLASH;
406    
407            static {
408                    try {
409                            _FILTERED_PROPERTY_DESCRIPTORS_CACHE_FIELD =
410                                    ReflectionUtil.getDeclaredField(
411                                            AbstractAutowireCapableBeanFactory.class,
412                                            "filteredPropertyDescriptorsCache");
413                    }
414                    catch (Exception e) {
415                            throw new LoggedExceptionInInitializerError(e);
416                    }
417            }
418    
419            private ArrayApplicationContext _arrayApplicationContext;
420            private ServiceWrapperRegistry _serviceWrapperRegistry;
421    
422    }