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