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