1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portal.deploy.hot;
16  
17  import com.liferay.portal.kernel.configuration.Configuration;
18  import com.liferay.portal.kernel.configuration.ConfigurationFactoryUtil;
19  import com.liferay.portal.kernel.deploy.hot.BaseHotDeployListener;
20  import com.liferay.portal.kernel.deploy.hot.HotDeployEvent;
21  import com.liferay.portal.kernel.deploy.hot.HotDeployException;
22  import com.liferay.portal.kernel.log.Log;
23  import com.liferay.portal.kernel.log.LogFactoryUtil;
24  import com.liferay.portal.kernel.plugin.PluginPackage;
25  import com.liferay.portal.kernel.plugin.Version;
26  import com.liferay.portal.kernel.util.GetterUtil;
27  import com.liferay.portal.kernel.util.HttpUtil;
28  import com.liferay.portal.kernel.util.StringPool;
29  import com.liferay.portal.kernel.util.Validator;
30  import com.liferay.portal.kernel.xml.DocumentException;
31  import com.liferay.portal.plugin.PluginPackageImpl;
32  import com.liferay.portal.plugin.PluginPackageUtil;
33  import com.liferay.portal.service.ServiceComponentLocalServiceUtil;
34  
35  import java.io.IOException;
36  import java.io.InputStream;
37  
38  import java.util.Properties;
39  import java.util.jar.Attributes;
40  import java.util.jar.Manifest;
41  
42  import javax.servlet.ServletContext;
43  
44  /**
45   * <a href="PluginPackageHotDeployListener.java.html"><b><i>View Source</i></b>
46   * </a>
47   *
48   * @author Jorge Ferrer
49   */
50  public class PluginPackageHotDeployListener extends BaseHotDeployListener {
51  
52      public static PluginPackage readPluginPackage(ServletContext servletContext)
53          throws DocumentException, IOException {
54  
55          PluginPackage pluginPackage = null;
56  
57          String servletContextName = servletContext.getServletContextName();
58  
59          String xml = HttpUtil.URLtoString(
60              servletContext.getResource("/WEB-INF/liferay-plugin-package.xml"));
61  
62          if (_log.isInfoEnabled()) {
63              if (servletContextName == null) {
64                  _log.info("Reading plugin package for the root context");
65              }
66              else {
67                  _log.info("Reading plugin package for " + servletContextName);
68              }
69          }
70  
71          if (xml == null) {
72              if (_log.isDebugEnabled()) {
73                  _log.debug("Reading plugin package from MANIFEST.MF");
74              }
75  
76              Attributes attributes = null;
77  
78              InputStream is = servletContext.getResourceAsStream(
79                  "/META-INF/MANIFEST.MF");
80  
81              if (is != null) {
82                  Manifest manifest = new Manifest(is);
83  
84                  attributes = manifest.getMainAttributes();
85              }
86              else {
87                  attributes = new Attributes();
88              }
89  
90              String artifactGroupId = attributes.getValue(
91                  "Implementation-Vendor-Id");
92  
93              if (Validator.isNull(artifactGroupId)) {
94                  artifactGroupId = attributes.getValue("Implementation-Vendor");
95              }
96  
97              if (Validator.isNull(artifactGroupId)) {
98                  artifactGroupId = GetterUtil.getString(
99                      attributes.getValue("Bundle-Vendor"), servletContextName);
100             }
101 
102             String artifactId = attributes.getValue("Implementation-Title");
103 
104             if (Validator.isNull(artifactId)) {
105                 artifactId = GetterUtil.getString(
106                     attributes.getValue("Bundle-Name"), servletContextName);
107             }
108 
109             String version = attributes.getValue("Implementation-Version");
110 
111             if (Validator.isNull(version)) {
112                 version = GetterUtil.getString(
113                     attributes.getValue("Bundle-Version"), Version.UNKNOWN);
114             }
115 
116             if (version.equals(Version.UNKNOWN) && _log.isWarnEnabled()) {
117                 _log.warn(
118                     "Plugin package on context " + servletContextName +
119                         " cannot be tracked because this WAR does not " +
120                             "contain a liferay-plugin-package.xml file");
121             }
122 
123             pluginPackage =
124                 new PluginPackageImpl(
125                     artifactGroupId + StringPool.SLASH + artifactId +
126                         StringPool.SLASH + version + StringPool.SLASH +
127                             "war");
128 
129             pluginPackage.setName(artifactId);
130 
131             String shortDescription = attributes.getValue("Bundle-Description");
132 
133             if (Validator.isNotNull(shortDescription)) {
134                 pluginPackage.setShortDescription(shortDescription);
135             }
136 
137             String pageURL = attributes.getValue("Bundle-DocURL");
138 
139             if (Validator.isNotNull(pageURL)) {
140                 pluginPackage.setPageURL(pageURL);
141             }
142         }
143         else {
144             if (_log.isDebugEnabled()) {
145                 _log.debug(
146                     "Reading plugin package from liferay-plugin-package.xml");
147             }
148 
149             pluginPackage = PluginPackageUtil.readPluginPackageXml(xml);
150         }
151 
152         pluginPackage.setContext(servletContextName);
153 
154         return pluginPackage;
155     }
156 
157     public void invokeDeploy(HotDeployEvent event) throws HotDeployException {
158         try {
159             doInvokeDeploy(event);
160         }
161         catch (Throwable t) {
162             throwHotDeployException(event, "Error registering plugins for ", t);
163         }
164     }
165 
166     public void invokeUndeploy(HotDeployEvent event) throws HotDeployException {
167         try {
168             doInvokeUndeploy(event);
169         }
170         catch (Throwable t) {
171             throwHotDeployException(
172                 event, "Error unregistering plugins for ", t);
173         }
174     }
175 
176     protected void destroyServiceComponent(
177             ServletContext servletContext, ClassLoader classLoader)
178         throws Exception {
179 
180         ServiceComponentLocalServiceUtil.destroyServiceComponent(
181             servletContext, classLoader);
182     }
183 
184     protected void doInvokeDeploy(HotDeployEvent event) throws Exception {
185         ServletContext servletContext = event.getServletContext();
186 
187         String servletContextName = servletContext.getServletContextName();
188 
189         if (_log.isDebugEnabled()) {
190             _log.debug("Invoking deploy for " + servletContextName);
191         }
192 
193         if (servletContext.getResource(
194                 "/WEB-INF/liferay-theme-loader.xml") != null) {
195 
196             return;
197         }
198 
199         PluginPackage pluginPackage = readPluginPackage(servletContext);
200 
201         if (pluginPackage == null) {
202             return;
203         }
204 
205         pluginPackage.setContext(servletContextName);
206 
207         event.setPluginPackage(pluginPackage);
208 
209         PluginPackageUtil.registerInstalledPluginPackage(pluginPackage);
210 
211         ClassLoader portletClassLoader = event.getContextClassLoader();
212 
213         initServiceComponent(servletContext, portletClassLoader);
214 
215         registerClpMessageListeners(servletContext, portletClassLoader);
216 
217         if (_log.isInfoEnabled()) {
218             _log.info(
219                 "Plugin package " + pluginPackage.getModuleId() +
220                     " registered successfully. It's now ready to be used.");
221         }
222     }
223 
224     protected void doInvokeUndeploy(HotDeployEvent event) throws Exception {
225         ServletContext servletContext = event.getServletContext();
226 
227         String servletContextName = servletContext.getServletContextName();
228 
229         if (_log.isDebugEnabled()) {
230             _log.debug("Invoking deploy for " + servletContextName);
231         }
232 
233         PluginPackage pluginPackage = readPluginPackage(servletContext);
234 
235         if (pluginPackage == null) {
236             return;
237         }
238 
239         event.setPluginPackage(pluginPackage);
240 
241         PluginPackageUtil.unregisterInstalledPluginPackage(pluginPackage);
242 
243         destroyServiceComponent(servletContext, event.getContextClassLoader());
244 
245         unregisterClpMessageListeners(servletContext);
246 
247         if (_log.isInfoEnabled()) {
248             _log.info(
249                 "Plugin package " + pluginPackage.getModuleId() +
250                     " unregistered successfully");
251         }
252     }
253 
254     protected void initServiceComponent(
255             ServletContext servletContext, ClassLoader classLoader)
256         throws Exception {
257 
258         Configuration serviceBuilderPropertiesConfiguration = null;
259 
260         try {
261             serviceBuilderPropertiesConfiguration =
262                 ConfigurationFactoryUtil.getConfiguration(
263                     classLoader, "service");
264         }
265         catch (Exception e) {
266             if (_log.isDebugEnabled()) {
267                 _log.debug("Unable to read service.properties");
268             }
269 
270             return;
271         }
272 
273         Properties serviceBuilderProperties =
274             serviceBuilderPropertiesConfiguration.getProperties();
275 
276         if (serviceBuilderProperties.size() == 0) {
277             return;
278         }
279 
280         String buildNamespace = GetterUtil.getString(
281             serviceBuilderProperties.getProperty("build.namespace"));
282         long buildNumber = GetterUtil.getLong(
283             serviceBuilderProperties.getProperty("build.number"));
284         long buildDate = GetterUtil.getLong(
285             serviceBuilderProperties.getProperty("build.date"));
286         boolean buildAutoUpgrade = GetterUtil.getBoolean(
287             serviceBuilderProperties.getProperty("build.auto.upgrade"), true);
288 
289         if (_log.isDebugEnabled()) {
290             _log.debug("Build namespace " + buildNamespace);
291             _log.debug("Build number " + buildNumber);
292             _log.debug("Build date " + buildDate);
293             _log.debug("Build auto upgrade " + buildAutoUpgrade);
294         }
295 
296         if (Validator.isNull(buildNamespace)) {
297             return;
298         }
299 
300         ServiceComponentLocalServiceUtil.initServiceComponent(
301             servletContext, classLoader, buildNamespace, buildNumber,
302             buildDate, buildAutoUpgrade);
303     }
304 
305     private static Log _log = LogFactoryUtil.getLog(
306         PluginPackageHotDeployListener.class);
307 
308 }