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