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