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