001    /**
002     * Copyright (c) 2000-2013 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.deploy.hot;
016    
017    import com.liferay.portal.dao.orm.hibernate.region.LiferayEhcacheRegionFactory;
018    import com.liferay.portal.dao.orm.hibernate.region.SingletonLiferayEhcacheRegionFactory;
019    import com.liferay.portal.kernel.bean.PortalBeanLocatorUtil;
020    import com.liferay.portal.kernel.cache.PortalCacheManager;
021    import com.liferay.portal.kernel.configuration.Configuration;
022    import com.liferay.portal.kernel.configuration.ConfigurationFactoryUtil;
023    import com.liferay.portal.kernel.deploy.hot.BaseHotDeployListener;
024    import com.liferay.portal.kernel.deploy.hot.HotDeployEvent;
025    import com.liferay.portal.kernel.deploy.hot.HotDeployException;
026    import com.liferay.portal.kernel.log.Log;
027    import com.liferay.portal.kernel.log.LogFactoryUtil;
028    import com.liferay.portal.kernel.plugin.PluginPackage;
029    import com.liferay.portal.kernel.servlet.ServletContextPool;
030    import com.liferay.portal.kernel.util.AggregateClassLoader;
031    import com.liferay.portal.kernel.util.GetterUtil;
032    import com.liferay.portal.kernel.util.PropsKeys;
033    import com.liferay.portal.kernel.util.Validator;
034    import com.liferay.portal.plugin.PluginPackageUtil;
035    import com.liferay.portal.service.ServiceComponentLocalServiceUtil;
036    import com.liferay.portal.util.ClassLoaderUtil;
037    import com.liferay.util.log4j.Log4JUtil;
038    import com.liferay.util.portlet.PortletProps;
039    
040    import java.lang.reflect.Method;
041    
042    import java.net.URL;
043    
044    import java.util.Properties;
045    
046    import javax.servlet.ServletContext;
047    
048    /**
049     * @author Jorge Ferrer
050     */
051    public class PluginPackageHotDeployListener extends BaseHotDeployListener {
052    
053            public static final String SERVICE_BUILDER_PROPERTIES =
054                    "SERVICE_BUILDER_PROPERTIES";
055    
056            @Override
057            public void invokeDeploy(HotDeployEvent hotDeployEvent)
058                    throws HotDeployException {
059    
060                    try {
061                            doInvokeDeploy(hotDeployEvent);
062                    }
063                    catch (Throwable t) {
064                            throwHotDeployException(
065                                    hotDeployEvent,
066                                    "Error registering plugins for " +
067                                            hotDeployEvent.getServletContextName(),
068                                    t);
069                    }
070            }
071    
072            @Override
073            public void invokeUndeploy(HotDeployEvent hotDeployEvent)
074                    throws HotDeployException {
075    
076                    try {
077                            doInvokeUndeploy(hotDeployEvent);
078                    }
079                    catch (Throwable t) {
080                            throwHotDeployException(
081                                    hotDeployEvent,
082                                    "Error unregistering plugins for " +
083                                            hotDeployEvent.getServletContextName(),
084                                    t);
085                    }
086            }
087    
088            protected void destroyServiceComponent(
089                            ServletContext servletContext, ClassLoader classLoader)
090                    throws Exception {
091    
092                    ServiceComponentLocalServiceUtil.destroyServiceComponent(
093                            servletContext, classLoader);
094            }
095    
096            protected void doInvokeDeploy(HotDeployEvent hotDeployEvent)
097                    throws Exception {
098    
099                    ServletContext servletContext = hotDeployEvent.getServletContext();
100    
101                    String servletContextName = servletContext.getServletContextName();
102    
103                    if (_log.isDebugEnabled()) {
104                            _log.debug("Invoking deploy for " + servletContextName);
105                    }
106    
107                    PluginPackage pluginPackage =
108                            PluginPackageUtil.readPluginPackageServletContext(servletContext);
109    
110                    if (pluginPackage == null) {
111                            return;
112                    }
113    
114                    if (servletContext.getResource(
115                                    "/WEB-INF/liferay-theme-loader.xml") != null) {
116    
117                            PluginPackageUtil.registerInstalledPluginPackage(pluginPackage);
118    
119                            return;
120                    }
121    
122                    pluginPackage.setContext(servletContextName);
123    
124                    hotDeployEvent.setPluginPackage(pluginPackage);
125    
126                    PluginPackageUtil.registerInstalledPluginPackage(pluginPackage);
127    
128                    ClassLoader classLoader = hotDeployEvent.getContextClassLoader();
129    
130                    initLogger(classLoader);
131                    initPortletProps(classLoader);
132                    initServiceComponent(servletContext, classLoader);
133    
134                    registerClpMessageListeners(servletContext, classLoader);
135    
136                    reconfigureCaches(classLoader);
137    
138                    if (_log.isInfoEnabled()) {
139                            _log.info(
140                                    "Plugin package " + pluginPackage.getModuleId() +
141                                            " registered successfully. It's now ready to be used.");
142                    }
143            }
144    
145            protected void doInvokeUndeploy(HotDeployEvent hotDeployEvent)
146                    throws Exception {
147    
148                    ServletContext servletContext = hotDeployEvent.getServletContext();
149    
150                    String servletContextName = servletContext.getServletContextName();
151    
152                    if (_log.isDebugEnabled()) {
153                            _log.debug("Invoking undeploy for " + servletContextName);
154                    }
155    
156                    PluginPackage pluginPackage =
157                            PluginPackageUtil.readPluginPackageServletContext(servletContext);
158    
159                    if (pluginPackage == null) {
160                            return;
161                    }
162    
163                    hotDeployEvent.setPluginPackage(pluginPackage);
164    
165                    PluginPackageUtil.unregisterInstalledPluginPackage(pluginPackage);
166    
167                    ServletContextPool.remove(servletContextName);
168    
169                    destroyServiceComponent(
170                            servletContext, hotDeployEvent.getContextClassLoader());
171    
172                    unregisterClpMessageListeners(servletContext);
173    
174                    if (_log.isInfoEnabled()) {
175                            _log.info(
176                                    "Plugin package " + pluginPackage.getModuleId() +
177                                            " unregistered successfully");
178                    }
179            }
180    
181            protected void initLogger(ClassLoader classLoader) {
182                    Log4JUtil.configureLog4J(
183                            classLoader.getResource("META-INF/portal-log4j.xml"));
184            }
185    
186            protected void initPortletProps(ClassLoader classLoader) throws Exception {
187                    if (classLoader.getResourceAsStream("portlet.properties") == null) {
188                            return;
189                    }
190    
191                    Class<?> clazz = classLoader.loadClass(PortletProps.class.getName());
192    
193                    Method method = clazz.getMethod("get", String.class);
194    
195                    method.invoke(null, "init");
196            }
197    
198            protected void initServiceComponent(
199                            ServletContext servletContext, ClassLoader classLoader)
200                    throws Exception {
201    
202                    Configuration serviceBuilderPropertiesConfiguration = null;
203    
204                    try {
205                            serviceBuilderPropertiesConfiguration =
206                                    ConfigurationFactoryUtil.getConfiguration(
207                                            classLoader, "service");
208                    }
209                    catch (Exception e) {
210                            if (_log.isDebugEnabled()) {
211                                    _log.debug("Unable to read service.properties");
212                            }
213    
214                            return;
215                    }
216    
217                    Properties serviceBuilderProperties =
218                            serviceBuilderPropertiesConfiguration.getProperties();
219    
220                    if (serviceBuilderProperties.size() == 0) {
221                            return;
222                    }
223    
224                    servletContext.setAttribute(
225                            SERVICE_BUILDER_PROPERTIES, serviceBuilderProperties);
226    
227                    String buildNamespace = GetterUtil.getString(
228                            serviceBuilderProperties.getProperty("build.namespace"));
229                    long buildNumber = GetterUtil.getLong(
230                            serviceBuilderProperties.getProperty("build.number"));
231                    long buildDate = GetterUtil.getLong(
232                            serviceBuilderProperties.getProperty("build.date"));
233                    boolean buildAutoUpgrade = GetterUtil.getBoolean(
234                            serviceBuilderProperties.getProperty("build.auto.upgrade"), true);
235    
236                    if (_log.isDebugEnabled()) {
237                            _log.debug("Build namespace " + buildNamespace);
238                            _log.debug("Build number " + buildNumber);
239                            _log.debug("Build date " + buildDate);
240                            _log.debug("Build auto upgrade " + buildAutoUpgrade);
241                    }
242    
243                    if (Validator.isNull(buildNamespace)) {
244                            return;
245                    }
246    
247                    ServiceComponentLocalServiceUtil.initServiceComponent(
248                            servletContext, classLoader, buildNamespace, buildNumber, buildDate,
249                            buildAutoUpgrade);
250            }
251    
252            protected void reconfigureCaches(ClassLoader classLoader) throws Exception {
253                    Configuration portletPropertiesConfiguration = null;
254    
255                    try {
256                            portletPropertiesConfiguration =
257                                    ConfigurationFactoryUtil.getConfiguration(
258                                            classLoader, "portlet");
259                    }
260                    catch (Exception e) {
261                            if (_log.isDebugEnabled()) {
262                                    _log.debug("Unable to read portlet.properties");
263                            }
264    
265                            return;
266                    }
267    
268                    String cacheConfigurationLocation = portletPropertiesConfiguration.get(
269                            PropsKeys.EHCACHE_SINGLE_VM_CONFIG_LOCATION);
270    
271                    reconfigureCaches(
272                            classLoader, cacheConfigurationLocation,
273                            _SINGLE_VM_PORTAL_CACHE_MANAGER_BEAN_NAME);
274    
275                    String clusterCacheConfigurationLocation =
276                            portletPropertiesConfiguration.get(
277                                    PropsKeys.EHCACHE_MULTI_VM_CONFIG_LOCATION);
278    
279                    reconfigureCaches(
280                            classLoader, clusterCacheConfigurationLocation,
281                            _MULTI_VM_PORTAL_CACHE_MANAGER_BEAN_NAME);
282    
283                    String hibernateCacheConfigurationPath =
284                            portletPropertiesConfiguration.get(
285                                    PropsKeys.NET_SF_EHCACHE_CONFIGURATION_RESOURCE_NAME);
286    
287                    reconfigureHibernateCache(classLoader, hibernateCacheConfigurationPath);
288            }
289    
290            protected void reconfigureCaches(
291                            ClassLoader classLoader, String cacheConfigurationPath,
292                            String portalCacheManagerBeanId)
293                    throws Exception {
294    
295                    if (Validator.isNull(cacheConfigurationPath)) {
296                            return;
297                    }
298    
299                    URL cacheConfigurationURL = classLoader.getResource(
300                            cacheConfigurationPath);
301    
302                    if (cacheConfigurationURL == null) {
303                            return;
304                    }
305    
306                    ClassLoader aggregateClassLoader =
307                            AggregateClassLoader.getAggregateClassLoader(
308                                    new ClassLoader[] {
309                                            ClassLoaderUtil.getPortalClassLoader(), classLoader
310                                    });
311    
312                    ClassLoader contextClassLoader =
313                            ClassLoaderUtil.getContextClassLoader();
314    
315                    try {
316                            ClassLoaderUtil.setContextClassLoader(aggregateClassLoader);
317    
318                            PortalCacheManager<?, ?> portalCacheManager =
319                                    (PortalCacheManager<?, ?>)PortalBeanLocatorUtil.locate(
320                                            portalCacheManagerBeanId);
321    
322                            if (_log.isInfoEnabled()) {
323                                    _log.info(
324                                            "Reconfiguring caches in cache manager " +
325                                                    portalCacheManagerBeanId + " using " +
326                                                            cacheConfigurationURL);
327                            }
328    
329                            portalCacheManager.reconfigureCaches(cacheConfigurationURL);
330                    }
331                    finally {
332                            ClassLoaderUtil.setContextClassLoader(contextClassLoader);
333                    }
334            }
335    
336            protected void reconfigureHibernateCache(
337                    ClassLoader classLoader, String hibernateCacheConfigurationPath) {
338    
339                    if (Validator.isNull(hibernateCacheConfigurationPath)) {
340                            return;
341                    }
342    
343                    LiferayEhcacheRegionFactory liferayEhcacheRegionFactory =
344                            SingletonLiferayEhcacheRegionFactory.getInstance();
345    
346                    URL configurationFile = classLoader.getResource(
347                            hibernateCacheConfigurationPath);
348    
349                    if (Validator.isNotNull(configurationFile)) {
350                            if (_log.isInfoEnabled()) {
351                                    _log.info(
352                                            "Reconfiguring Hibernate caches using " +
353                                                    configurationFile);
354                            }
355    
356                            liferayEhcacheRegionFactory.reconfigureCaches(configurationFile);
357                    }
358            }
359    
360            private static final String _MULTI_VM_PORTAL_CACHE_MANAGER_BEAN_NAME =
361                    "com.liferay.portal.kernel.cache.MultiVMPortalCacheManager";
362    
363            private static final String _SINGLE_VM_PORTAL_CACHE_MANAGER_BEAN_NAME =
364                    "com.liferay.portal.kernel.cache.SingleVMPortalCacheManager";
365    
366            private static Log _log = LogFactoryUtil.getLog(
367                    PluginPackageHotDeployListener.class);
368    
369    }