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.bean.BeanReferenceRefreshUtil;
062    import com.liferay.portal.util.InitUtil;
063    import com.liferay.portal.util.PropsValues;
064    import com.liferay.portal.util.WebAppPool;
065    import com.liferay.portlet.PortletContextBagPool;
066    import com.liferay.registry.dependency.ServiceDependencyListener;
067    import com.liferay.registry.dependency.ServiceDependencyManager;
068    
069    import java.beans.PropertyDescriptor;
070    
071    import java.io.Closeable;
072    import java.io.File;
073    import java.io.IOException;
074    
075    import java.lang.reflect.Field;
076    
077    import java.util.Map;
078    
079    import javax.servlet.ServletContext;
080    import javax.servlet.ServletContextEvent;
081    
082    import javax.sql.DataSource;
083    
084    import org.springframework.beans.CachedIntrospectionResults;
085    import org.springframework.beans.factory.config.AutowireCapableBeanFactory;
086    import org.springframework.beans.factory.support.AbstractAutowireCapableBeanFactory;
087    import org.springframework.context.ApplicationContext;
088    import org.springframework.web.context.ContextLoader;
089    import org.springframework.web.context.ContextLoaderListener;
090    
091    /**
092     * @author Michael Young
093     * @author Shuyang Zhou
094     * @author Raymond Aug??
095     */
096    public class PortalContextLoaderListener extends ContextLoaderListener {
097    
098            public static String getPortalServletContextName() {
099                    return _portalServletContextName;
100            }
101    
102            public static String getPortalServletContextPath() {
103                    return _portalServletContextPath;
104            }
105    
106            @Override
107            public void contextDestroyed(ServletContextEvent servletContextEvent) {
108                    PortalContextLoaderLifecycleThreadLocal.setDestroying(true);
109    
110                    ThreadLocalCacheManager.destroy();
111    
112                    if (_serviceWrapperRegistry != null) {
113                            _serviceWrapperRegistry.close();
114                    }
115    
116                    try {
117                            ClearThreadLocalUtil.clearThreadLocal();
118                    }
119                    catch (Exception e) {
120                            _log.error(e, e);
121                    }
122    
123                    try {
124                            ClearTimerThreadUtil.clearTimerThread();
125                    }
126                    catch (Exception e) {
127                            _log.error(e, e);
128                    }
129    
130                    try {
131                            DirectServletRegistryUtil.clearServlets();
132                    }
133                    catch (Exception e) {
134                            _log.error(e, e);
135                    }
136    
137                    try {
138                            HotDeployUtil.reset();
139                    }
140                    catch (Exception e) {
141                            _log.error(e, e);
142                    }
143    
144                    try {
145                            ModuleFrameworkUtilAdapter.stopRuntime();
146                    }
147                    catch (Exception e) {
148                            _log.error(e, e);
149                    }
150    
151                    try {
152                            PortalLifecycleUtil.reset();
153                    }
154                    catch (Exception e) {
155                            _log.error(e, e);
156                    }
157    
158                    closeDataSource("counterDataSourceImpl");
159    
160                    closeDataSource("liferayDataSourceImpl");
161    
162                    try {
163                            super.contextDestroyed(servletContextEvent);
164    
165                            try {
166                                    ModuleFrameworkUtilAdapter.stopFramework(
167                                            PropsValues.MODULE_FRAMEWORK_STOP_WAIT_TIMEOUT);
168                            }
169                            catch (Exception e) {
170                                    _log.error(e, e);
171                            }
172    
173                            _arrayApplicationContext.close();
174                    }
175                    finally {
176                            PortalContextLoaderLifecycleThreadLocal.setDestroying(false);
177    
178                            SecurityManagerUtil.destroy();
179                    }
180            }
181    
182            @Override
183            public void contextInitialized(ServletContextEvent servletContextEvent) {
184                    Thread currentThread = Thread.currentThread();
185    
186                    SystemProperties.load(currentThread.getContextClassLoader());
187    
188                    DBManagerUtil.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                    File tempDir = (File)servletContext.getAttribute(
237                            JavaConstants.JAVAX_SERVLET_CONTEXT_TEMPDIR);
238    
239                    PropsValues.LIFERAY_WEB_PORTAL_CONTEXT_TEMPDIR =
240                            tempDir.getAbsolutePath();
241    
242                    try {
243                            ModuleFrameworkUtilAdapter.initFramework();
244    
245                            _arrayApplicationContext = new ArrayApplicationContext(
246                                    PropsValues.SPRING_INFRASTRUCTURE_CONFIGS);
247    
248                            servletContext.setAttribute(
249                                    PortalApplicationContext.PARENT_APPLICATION_CONTEXT,
250                                    _arrayApplicationContext);
251    
252                            ModuleFrameworkUtilAdapter.registerContext(
253                                    _arrayApplicationContext);
254    
255                            ModuleFrameworkUtilAdapter.startFramework();
256                    }
257                    catch (Exception e) {
258                            throw new RuntimeException(e);
259                    }
260    
261                    ServiceDependencyManager serviceDependencyManager =
262                            new ServiceDependencyManager();
263    
264                    serviceDependencyManager.addServiceDependencyListener(
265                            new ServiceDependencyListener() {
266    
267                                    @Override
268                                    public void destroy() {
269                                    }
270    
271                                    @Override
272                                    public void dependenciesFulfilled() {
273                                            _serviceWrapperRegistry = new ServiceWrapperRegistry();
274                                    }
275    
276                            });
277    
278                    serviceDependencyManager.registerDependencies(
279                            MessageBus.class, PortalExecutorManager.class,
280                            SchedulerEngineHelper.class,
281                            SingleDestinationMessageSenderFactory.class);
282    
283                    ClassLoader portalClassLoader = ClassLoaderUtil.getPortalClassLoader();
284    
285                    ClassLoaderPool.register(_portalServletContextName, portalClassLoader);
286    
287                    PortalContextLoaderLifecycleThreadLocal.setInitializing(true);
288    
289                    try {
290                            super.contextInitialized(servletContextEvent);
291                    }
292                    finally {
293                            PortalContextLoaderLifecycleThreadLocal.setInitializing(false);
294                    }
295    
296                    ApplicationContext applicationContext =
297                            ContextLoader.getCurrentWebApplicationContext();
298    
299                    try {
300                            BeanReferenceRefreshUtil.refresh(
301                                    applicationContext.getAutowireCapableBeanFactory());
302                    }
303                    catch (Exception e) {
304                            _log.error(e, e);
305                    }
306    
307                    if (PropsValues.CACHE_CLEAR_ON_CONTEXT_INITIALIZATION) {
308                            CacheRegistryUtil.clear();
309                            PortletContextBagPool.clear();
310                            WebAppPool.clear();
311    
312                            TemplateResourceLoaderUtil.clearCache();
313    
314                            ServletContextPool.clear();
315    
316                            MultiVMPoolUtil.clear();
317                            SingleVMPoolUtil.clear();
318                    }
319    
320                    ServletContextPool.put(_portalServletContextName, servletContext);
321    
322                    BeanLocatorImpl beanLocatorImpl = new BeanLocatorImpl(
323                            portalClassLoader, applicationContext);
324    
325                    PortalBeanLocatorUtil.setBeanLocator(beanLocatorImpl);
326    
327                    ClassLoader classLoader = portalClassLoader;
328    
329                    while (classLoader != null) {
330                            CachedIntrospectionResults.clearClassLoader(classLoader);
331    
332                            classLoader = classLoader.getParent();
333                    }
334    
335                    AutowireCapableBeanFactory autowireCapableBeanFactory =
336                            applicationContext.getAutowireCapableBeanFactory();
337    
338                    clearFilteredPropertyDescriptorsCache(autowireCapableBeanFactory);
339    
340                    try {
341                            ModuleFrameworkUtilAdapter.registerContext(applicationContext);
342    
343                            ModuleFrameworkUtilAdapter.startRuntime();
344                    }
345                    catch (Exception e) {
346                            throw new RuntimeException(e);
347                    }
348    
349                    CustomJspBagRegistryUtil.getCustomJspBags();
350    
351                    initListeners(servletContext);
352            }
353    
354            protected void clearFilteredPropertyDescriptorsCache(
355                    AutowireCapableBeanFactory autowireCapableBeanFactory) {
356    
357                    try {
358                            Map<Class<?>, PropertyDescriptor[]>
359                                    filteredPropertyDescriptorsCache =
360                                            (Map<Class<?>, PropertyDescriptor[]>)
361                                                    _FILTERED_PROPERTY_DESCRIPTORS_CACHE_FIELD.get(
362                                                            autowireCapableBeanFactory);
363    
364                            filteredPropertyDescriptorsCache.clear();
365                    }
366                    catch (Exception e) {
367                            _log.error(e, e);
368                    }
369            }
370    
371            protected void closeDataSource(String name) {
372                    DataSource dataSource = (DataSource)PortalBeanLocatorUtil.locate(name);
373    
374                    if (dataSource instanceof Closeable) {
375                            try {
376                                    Closeable closeable = (Closeable)dataSource;
377    
378                                    closeable.close();
379                            }
380                            catch (IOException e) {
381                                    _log.error(e, e);
382                            }
383                    }
384            }
385    
386            protected void initListeners(ServletContext servletContext) {
387                    if (PropsValues.SESSION_VERIFY_SERIALIZABLE_ATTRIBUTE) {
388                            servletContext.addListener(
389                                    SerializableSessionAttributeListener.class);
390                    }
391            }
392    
393            private static final Field _FILTERED_PROPERTY_DESCRIPTORS_CACHE_FIELD;
394    
395            private static final Log _log = LogFactoryUtil.getLog(
396                    PortalContextLoaderListener.class);
397    
398            private static String _portalServletContextName = StringPool.BLANK;
399            private static String _portalServletContextPath = StringPool.SLASH;
400    
401            static {
402                    try {
403                            _FILTERED_PROPERTY_DESCRIPTORS_CACHE_FIELD =
404                                    ReflectionUtil.getDeclaredField(
405                                            AbstractAutowireCapableBeanFactory.class,
406                                            "filteredPropertyDescriptorsCache");
407                    }
408                    catch (Exception e) {
409                            throw new LoggedExceptionInInitializerError(e);
410                    }
411            }
412    
413            private ArrayApplicationContext _arrayApplicationContext;
414            private ServiceWrapperRegistry _serviceWrapperRegistry;
415    
416    }