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.DBFactoryUtil;
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                    try {
190                            Class.forName(SystemProperties.class.getName());
191                    }
192                    catch (ClassNotFoundException cnfe) {
193                            throw new RuntimeException(cnfe);
194                    }
195    
196                    DBFactoryUtil.reset();
197                    DeployManagerUtil.reset();
198                    InstancePool.reset();
199                    MethodCache.reset();
200                    PortalBeanLocatorUtil.reset();
201                    PortletBagPool.reset();
202    
203                    ReferenceRegistry.releaseReferences();
204    
205                    FieldInterceptionHelperUtil.initialize();
206    
207                    final ServletContext servletContext =
208                            servletContextEvent.getServletContext();
209    
210                    String portalLibDir = servletContext.getRealPath("/WEB-INF/lib");
211    
212                    portalLibDir = StringUtil.replace(
213                            portalLibDir, CharPool.BACK_SLASH, CharPool.FORWARD_SLASH);
214    
215                    if (Validator.isNotNull(portalLibDir)) {
216                            SystemProperties.set(
217                                    PropsKeys.LIFERAY_LIB_PORTAL_DIR, portalLibDir);
218                    }
219    
220                    InitUtil.init();
221    
222                    _portalServletContextName = servletContext.getServletContextName();
223    
224                    if (_portalServletContextName == null) {
225                            _portalServletContextName = StringPool.BLANK;
226                    }
227    
228                    if (ServerDetector.isJetty() &&
229                            _portalServletContextName.equals(StringPool.SLASH)) {
230    
231                            _portalServletContextName = StringPool.BLANK;
232                    }
233    
234                    _portalServletContextPath = servletContext.getContextPath();
235    
236                    if (ServerDetector.isWebSphere() &&
237                            _portalServletContextPath.isEmpty()) {
238    
239                            _portalServletContextName = StringPool.BLANK;
240                    }
241    
242                    ClassPathUtil.initializeClassPaths(servletContext);
243    
244                    File tempDir = (File)servletContext.getAttribute(
245                            JavaConstants.JAVAX_SERVLET_CONTEXT_TEMPDIR);
246    
247                    PropsValues.LIFERAY_WEB_PORTAL_CONTEXT_TEMPDIR =
248                            tempDir.getAbsolutePath();
249    
250                    try {
251                            ModuleFrameworkUtilAdapter.initFramework();
252    
253                            _arrayApplicationContext = new ArrayApplicationContext(
254                                    PropsValues.SPRING_INFRASTRUCTURE_CONFIGS);
255    
256                            servletContext.setAttribute(
257                                    PortalApplicationContext.PARENT_APPLICATION_CONTEXT,
258                                    _arrayApplicationContext);
259    
260                            ModuleFrameworkUtilAdapter.registerContext(
261                                    _arrayApplicationContext);
262    
263                            ModuleFrameworkUtilAdapter.startFramework();
264                    }
265                    catch (Exception e) {
266                            throw new RuntimeException(e);
267                    }
268    
269                    ServiceDependencyManager serviceDependencyManager =
270                            new ServiceDependencyManager();
271    
272                    serviceDependencyManager.addServiceDependencyListener(
273                            new ServiceDependencyListener() {
274    
275                                    @Override
276                                    public void destroy() {
277                                    }
278    
279                                    @Override
280                                    public void dependenciesFulfilled() {
281                                            _indexerPostProcessorRegistry =
282                                                    new IndexerPostProcessorRegistry();
283                                            _serviceWrapperRegistry = new ServiceWrapperRegistry();
284                                    }
285    
286                            });
287    
288                    serviceDependencyManager.registerDependencies(
289                            MessageBus.class, PortalExecutorManager.class,
290                            SchedulerEngineHelper.class,
291                            SingleDestinationMessageSenderFactory.class);
292    
293                    ClassLoader portalClassLoader = ClassLoaderUtil.getPortalClassLoader();
294    
295                    ClassLoaderPool.register(_portalServletContextName, portalClassLoader);
296    
297                    PortalContextLoaderLifecycleThreadLocal.setInitializing(true);
298    
299                    try {
300                            super.contextInitialized(servletContextEvent);
301                    }
302                    finally {
303                            PortalContextLoaderLifecycleThreadLocal.setInitializing(false);
304                    }
305    
306                    ApplicationContext applicationContext =
307                            ContextLoader.getCurrentWebApplicationContext();
308    
309                    try {
310                            BeanReferenceRefreshUtil.refresh(
311                                    applicationContext.getAutowireCapableBeanFactory());
312                    }
313                    catch (Exception e) {
314                            _log.error(e, e);
315                    }
316    
317                    if (PropsValues.CACHE_CLEAR_ON_CONTEXT_INITIALIZATION) {
318                            CacheRegistryUtil.clear();
319                            PortletContextBagPool.clear();
320                            WebAppPool.clear();
321    
322                            TemplateResourceLoaderUtil.clearCache();
323    
324                            ServletContextPool.clear();
325    
326                            MultiVMPoolUtil.clear();
327                            SingleVMPoolUtil.clear();
328                    }
329    
330                    ServletContextPool.put(_portalServletContextName, servletContext);
331    
332                    BeanLocatorImpl beanLocatorImpl = new BeanLocatorImpl(
333                            portalClassLoader, applicationContext);
334    
335                    PortalBeanLocatorUtil.setBeanLocator(beanLocatorImpl);
336    
337                    ClassLoader classLoader = portalClassLoader;
338    
339                    while (classLoader != null) {
340                            CachedIntrospectionResults.clearClassLoader(classLoader);
341    
342                            classLoader = classLoader.getParent();
343                    }
344    
345                    AutowireCapableBeanFactory autowireCapableBeanFactory =
346                            applicationContext.getAutowireCapableBeanFactory();
347    
348                    clearFilteredPropertyDescriptorsCache(autowireCapableBeanFactory);
349    
350                    try {
351                            ModuleFrameworkUtilAdapter.registerContext(applicationContext);
352    
353                            ModuleFrameworkUtilAdapter.startRuntime();
354                    }
355                    catch (Exception e) {
356                            throw new RuntimeException(e);
357                    }
358    
359                    CustomJspBagRegistryUtil.getCustomJspBags();
360    
361                    initListeners(servletContext);
362            }
363    
364            protected void clearFilteredPropertyDescriptorsCache(
365                    AutowireCapableBeanFactory autowireCapableBeanFactory) {
366    
367                    try {
368                            Map<Class<?>, PropertyDescriptor[]>
369                                    filteredPropertyDescriptorsCache =
370                                            (Map<Class<?>, PropertyDescriptor[]>)
371                                                    _FILTERED_PROPERTY_DESCRIPTORS_CACHE_FIELD.get(
372                                                            autowireCapableBeanFactory);
373    
374                            filteredPropertyDescriptorsCache.clear();
375                    }
376                    catch (Exception e) {
377                            _log.error(e, e);
378                    }
379            }
380    
381            protected void closeDataSource(String name) {
382                    DataSource dataSource = (DataSource)PortalBeanLocatorUtil.locate(name);
383    
384                    if (dataSource instanceof Closeable) {
385                            try {
386                                    Closeable closeable = (Closeable)dataSource;
387    
388                                    closeable.close();
389                            }
390                            catch (IOException e) {
391                                    _log.error(e, e);
392                            }
393                    }
394            }
395    
396            protected void initListeners(ServletContext servletContext) {
397                    if (PropsValues.SESSION_VERIFY_SERIALIZABLE_ATTRIBUTE) {
398                            servletContext.addListener(
399                                    SerializableSessionAttributeListener.class);
400                    }
401            }
402    
403            private static final Field _FILTERED_PROPERTY_DESCRIPTORS_CACHE_FIELD;
404    
405            private static final Log _log = LogFactoryUtil.getLog(
406                    PortalContextLoaderListener.class);
407    
408            private static String _portalServletContextName = StringPool.BLANK;
409            private static String _portalServletContextPath = StringPool.SLASH;
410    
411            static {
412                    try {
413                            _FILTERED_PROPERTY_DESCRIPTORS_CACHE_FIELD =
414                                    ReflectionUtil.getDeclaredField(
415                                            AbstractAutowireCapableBeanFactory.class,
416                                            "filteredPropertyDescriptorsCache");
417                    }
418                    catch (Exception e) {
419                            throw new LoggedExceptionInInitializerError(e);
420                    }
421            }
422    
423            private ArrayApplicationContext _arrayApplicationContext;
424            private IndexerPostProcessorRegistry _indexerPostProcessorRegistry;
425            private ServiceWrapperRegistry _serviceWrapperRegistry;
426    
427    }