001    /**
002     * Copyright (c) 2000-2010 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.kernel.configuration.Configuration;
018    import com.liferay.portal.kernel.configuration.ConfigurationFactoryUtil;
019    import com.liferay.portal.kernel.deploy.hot.BaseHotDeployListener;
020    import com.liferay.portal.kernel.deploy.hot.HotDeployEvent;
021    import com.liferay.portal.kernel.deploy.hot.HotDeployException;
022    import com.liferay.portal.kernel.log.Log;
023    import com.liferay.portal.kernel.log.LogFactoryUtil;
024    import com.liferay.portal.kernel.plugin.PluginPackage;
025    import com.liferay.portal.kernel.plugin.Version;
026    import com.liferay.portal.kernel.servlet.PortletServlet;
027    import com.liferay.portal.kernel.servlet.ServletContextPool;
028    import com.liferay.portal.kernel.util.GetterUtil;
029    import com.liferay.portal.kernel.util.HttpUtil;
030    import com.liferay.portal.kernel.util.StringPool;
031    import com.liferay.portal.kernel.util.Validator;
032    import com.liferay.portal.kernel.xml.DocumentException;
033    import com.liferay.portal.plugin.PluginPackageImpl;
034    import com.liferay.portal.plugin.PluginPackageUtil;
035    import com.liferay.portal.service.ServiceComponentLocalServiceUtil;
036    
037    import java.io.IOException;
038    import java.io.InputStream;
039    
040    import java.util.Properties;
041    import java.util.jar.Attributes;
042    import java.util.jar.Manifest;
043    
044    import javax.servlet.ServletContext;
045    
046    /**
047     * @author Jorge Ferrer
048     */
049    public class PluginPackageHotDeployListener extends BaseHotDeployListener {
050    
051            public static PluginPackage readPluginPackage(ServletContext servletContext)
052                    throws DocumentException, IOException {
053    
054                    PluginPackage pluginPackage = null;
055    
056                    String servletContextName = servletContext.getServletContextName();
057    
058                    String xml = HttpUtil.URLtoString(
059                            servletContext.getResource("/WEB-INF/liferay-plugin-package.xml"));
060    
061                    if (_log.isInfoEnabled()) {
062                            if (servletContextName == null) {
063                                    _log.info("Reading plugin package for the root context");
064                            }
065                            else {
066                                    _log.info("Reading plugin package for " + servletContextName);
067                            }
068                    }
069    
070                    if (xml == null) {
071                            if (_log.isDebugEnabled()) {
072                                    _log.debug("Reading plugin package from MANIFEST.MF");
073                            }
074    
075                            Attributes attributes = null;
076    
077                            InputStream is = servletContext.getResourceAsStream(
078                                    "/META-INF/MANIFEST.MF");
079    
080                            if (is != null) {
081                                    Manifest manifest = new Manifest(is);
082    
083                                    attributes = manifest.getMainAttributes();
084                            }
085                            else {
086                                    attributes = new Attributes();
087                            }
088    
089                            String artifactGroupId = attributes.getValue(
090                                    "Implementation-Vendor-Id");
091    
092                            if (Validator.isNull(artifactGroupId)) {
093                                    artifactGroupId = attributes.getValue("Implementation-Vendor");
094                            }
095    
096                            if (Validator.isNull(artifactGroupId)) {
097                                    artifactGroupId = GetterUtil.getString(
098                                            attributes.getValue("Bundle-Vendor"), servletContextName);
099                            }
100    
101                            String artifactId = attributes.getValue("Implementation-Title");
102    
103                            if (Validator.isNull(artifactId)) {
104                                    artifactId = GetterUtil.getString(
105                                            attributes.getValue("Bundle-Name"), servletContextName);
106                            }
107    
108                            String version = attributes.getValue("Implementation-Version");
109    
110                            if (Validator.isNull(version)) {
111                                    version = GetterUtil.getString(
112                                            attributes.getValue("Bundle-Version"), Version.UNKNOWN);
113                            }
114    
115                            if (version.equals(Version.UNKNOWN) && _log.isWarnEnabled()) {
116                                    _log.warn(
117                                            "Plugin package on context " + servletContextName +
118                                                    " cannot be tracked because this WAR does not " +
119                                                            "contain a liferay-plugin-package.xml file");
120                            }
121    
122                            pluginPackage =
123                                    new PluginPackageImpl(
124                                            artifactGroupId + StringPool.SLASH + artifactId +
125                                                    StringPool.SLASH + version + StringPool.SLASH +
126                                                            "war");
127    
128                            pluginPackage.setName(artifactId);
129    
130                            String shortDescription = attributes.getValue("Bundle-Description");
131    
132                            if (Validator.isNotNull(shortDescription)) {
133                                    pluginPackage.setShortDescription(shortDescription);
134                            }
135    
136                            String pageURL = attributes.getValue("Bundle-DocURL");
137    
138                            if (Validator.isNotNull(pageURL)) {
139                                    pluginPackage.setPageURL(pageURL);
140                            }
141                    }
142                    else {
143                            if (_log.isDebugEnabled()) {
144                                    _log.debug(
145                                            "Reading plugin package from liferay-plugin-package.xml");
146                            }
147    
148                            pluginPackage = PluginPackageUtil.readPluginPackageXml(xml);
149                    }
150    
151                    pluginPackage.setContext(servletContextName);
152    
153                    return pluginPackage;
154            }
155    
156            public void invokeDeploy(HotDeployEvent event) throws HotDeployException {
157                    try {
158                            doInvokeDeploy(event);
159                    }
160                    catch (Throwable t) {
161                            throwHotDeployException(event, "Error registering plugins for ", t);
162                    }
163            }
164    
165            public void invokeUndeploy(HotDeployEvent event) throws HotDeployException {
166                    try {
167                            doInvokeUndeploy(event);
168                    }
169                    catch (Throwable t) {
170                            throwHotDeployException(
171                                    event, "Error unregistering plugins for ", t);
172                    }
173            }
174    
175            protected void destroyServiceComponent(
176                            ServletContext servletContext, ClassLoader classLoader)
177                    throws Exception {
178    
179                    ServiceComponentLocalServiceUtil.destroyServiceComponent(
180                            servletContext, classLoader);
181            }
182    
183            protected void doInvokeDeploy(HotDeployEvent event) throws Exception {
184                    ServletContext servletContext = event.getServletContext();
185    
186                    String servletContextName = servletContext.getServletContextName();
187    
188                    if (_log.isDebugEnabled()) {
189                            _log.debug("Invoking deploy for " + servletContextName);
190                    }
191    
192                    if (servletContext.getResource(
193                                    "/WEB-INF/liferay-theme-loader.xml") != null) {
194    
195                            return;
196                    }
197    
198                    PluginPackage pluginPackage = readPluginPackage(servletContext);
199    
200                    if (pluginPackage == null) {
201                            return;
202                    }
203    
204                    pluginPackage.setContext(servletContextName);
205    
206                    event.setPluginPackage(pluginPackage);
207    
208                    PluginPackageUtil.registerInstalledPluginPackage(pluginPackage);
209    
210                    ClassLoader portletClassLoader = event.getContextClassLoader();
211    
212                    servletContext.setAttribute(
213                            PortletServlet.PORTLET_CLASS_LOADER, portletClassLoader);
214    
215                    ServletContextPool.put(servletContextName, servletContext);
216    
217                    initServiceComponent(servletContext, portletClassLoader);
218    
219                    registerClpMessageListeners(servletContext, portletClassLoader);
220    
221                    if (_log.isInfoEnabled()) {
222                            _log.info(
223                                    "Plugin package " + pluginPackage.getModuleId() +
224                                            " registered successfully. It's now ready to be used.");
225                    }
226            }
227    
228            protected void doInvokeUndeploy(HotDeployEvent event) throws Exception {
229                    ServletContext servletContext = event.getServletContext();
230    
231                    String servletContextName = servletContext.getServletContextName();
232    
233                    if (_log.isDebugEnabled()) {
234                            _log.debug("Invoking deploy for " + servletContextName);
235                    }
236    
237                    PluginPackage pluginPackage = readPluginPackage(servletContext);
238    
239                    if (pluginPackage == null) {
240                            return;
241                    }
242    
243                    event.setPluginPackage(pluginPackage);
244    
245                    PluginPackageUtil.unregisterInstalledPluginPackage(pluginPackage);
246    
247                    ServletContextPool.remove(servletContextName);
248    
249                    destroyServiceComponent(servletContext, event.getContextClassLoader());
250    
251                    unregisterClpMessageListeners(servletContext);
252    
253                    if (_log.isInfoEnabled()) {
254                            _log.info(
255                                    "Plugin package " + pluginPackage.getModuleId() +
256                                            " unregistered successfully");
257                    }
258            }
259    
260            protected void initServiceComponent(
261                            ServletContext servletContext, ClassLoader classLoader)
262                    throws Exception {
263    
264                    Configuration serviceBuilderPropertiesConfiguration = null;
265    
266                    try {
267                            serviceBuilderPropertiesConfiguration =
268                                    ConfigurationFactoryUtil.getConfiguration(
269                                            classLoader, "service");
270                    }
271                    catch (Exception e) {
272                            if (_log.isDebugEnabled()) {
273                                    _log.debug("Unable to read service.properties");
274                            }
275    
276                            return;
277                    }
278    
279                    Properties serviceBuilderProperties =
280                            serviceBuilderPropertiesConfiguration.getProperties();
281    
282                    if (serviceBuilderProperties.size() == 0) {
283                            return;
284                    }
285    
286                    String buildNamespace = GetterUtil.getString(
287                            serviceBuilderProperties.getProperty("build.namespace"));
288                    long buildNumber = GetterUtil.getLong(
289                            serviceBuilderProperties.getProperty("build.number"));
290                    long buildDate = GetterUtil.getLong(
291                            serviceBuilderProperties.getProperty("build.date"));
292                    boolean buildAutoUpgrade = GetterUtil.getBoolean(
293                            serviceBuilderProperties.getProperty("build.auto.upgrade"), true);
294    
295                    if (_log.isDebugEnabled()) {
296                            _log.debug("Build namespace " + buildNamespace);
297                            _log.debug("Build number " + buildNumber);
298                            _log.debug("Build date " + buildDate);
299                            _log.debug("Build auto upgrade " + buildAutoUpgrade);
300                    }
301    
302                    if (Validator.isNull(buildNamespace)) {
303                            return;
304                    }
305    
306                    ServiceComponentLocalServiceUtil.initServiceComponent(
307                            servletContext, classLoader, buildNamespace, buildNumber,
308                            buildDate, buildAutoUpgrade);
309            }
310    
311            private static Log _log = LogFactoryUtil.getLog(
312                    PluginPackageHotDeployListener.class);
313    
314    }