1   /**
2    * Copyright (c) 2000-2008 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.deploy.hot;
24  
25  import com.liferay.portal.kernel.bean.PortletBeanLocatorUtil;
26  import com.liferay.portal.kernel.cache.CacheRegistry;
27  import com.liferay.portal.kernel.configuration.Configuration;
28  import com.liferay.portal.kernel.configuration.ConfigurationFactoryUtil;
29  import com.liferay.portal.kernel.deploy.hot.HotDeployEvent;
30  import com.liferay.portal.kernel.deploy.hot.HotDeployException;
31  import com.liferay.portal.kernel.plugin.PluginPackage;
32  import com.liferay.portal.kernel.util.GetterUtil;
33  import com.liferay.portal.kernel.util.HttpUtil;
34  import com.liferay.portal.kernel.util.StringPool;
35  import com.liferay.portal.kernel.util.Validator;
36  import com.liferay.portal.plugin.PluginPackageImpl;
37  import com.liferay.portal.plugin.PluginPackageUtil;
38  import com.liferay.portal.service.ServiceComponentLocalServiceUtil;
39  import com.liferay.util.Version;
40  
41  import java.io.IOException;
42  import java.io.InputStream;
43  
44  import java.util.Properties;
45  import java.util.jar.Attributes;
46  import java.util.jar.Manifest;
47  
48  import javax.servlet.ServletContext;
49  
50  import org.apache.commons.logging.Log;
51  import org.apache.commons.logging.LogFactory;
52  
53  import org.dom4j.DocumentException;
54  
55  /**
56   * <a href="PluginPackageHotDeployListener.java.html"><b><i>View Source</i></b>
57   * </a>
58   *
59   * @author Jorge Ferrer
60   *
61   */
62  public class PluginPackageHotDeployListener extends BaseHotDeployListener {
63  
64      public static PluginPackage readPluginPackage(ServletContext servletContext)
65          throws DocumentException, IOException {
66  
67          PluginPackage pluginPackage = null;
68  
69          String servletContextName = servletContext.getServletContextName();
70  
71          String xml = HttpUtil.URLtoString(
72              servletContext.getResource("/WEB-INF/liferay-plugin-package.xml"));
73  
74          if (_log.isInfoEnabled()) {
75              if (servletContextName == null) {
76                  _log.info("Reading plugin package for the root context");
77              }
78              else {
79                  _log.info("Reading plugin package for " + servletContextName);
80              }
81          }
82  
83          if (xml == null) {
84              if (_log.isDebugEnabled()) {
85                  _log.debug("Reading plugin package from MANIFEST.MF");
86              }
87  
88              Attributes attributes = null;
89  
90              InputStream is = servletContext.getResourceAsStream(
91                  "/META-INF/MANIFEST.MF");
92  
93              if (is != null) {
94                  Manifest manifest = new Manifest(is);
95  
96                  attributes = manifest.getMainAttributes();
97              }
98              else {
99                  attributes = new Attributes();
100             }
101 
102             String artifactGroupId = attributes.getValue(
103                 "Implementation-Vendor-Id");
104 
105             if (Validator.isNull(artifactGroupId)) {
106                 artifactGroupId = attributes.getValue("Implementation-Vendor");
107             }
108 
109             if (Validator.isNull(artifactGroupId)) {
110                 artifactGroupId = GetterUtil.getString(
111                     attributes.getValue("Bundle-Vendor"), servletContextName);
112             }
113 
114             String artifactId = attributes.getValue("Implementation-Title");
115 
116             if (Validator.isNull(artifactId)) {
117                 artifactId = GetterUtil.getString(
118                     attributes.getValue("Bundle-Name"), servletContextName);
119             }
120 
121             String version = attributes.getValue("Implementation-Version");
122 
123             if (Validator.isNull(version)) {
124                 version = GetterUtil.getString(
125                     attributes.getValue("Bundle-Version"), Version.UNKNOWN);
126             }
127 
128             if (version.equals(Version.UNKNOWN) && _log.isWarnEnabled()) {
129                 _log.warn(
130                     "Plugin package on context " + servletContextName +
131                         " cannot be tracked because this WAR does not " +
132                             "contain a liferay-plugin-package.xml file");
133             }
134 
135             pluginPackage =
136                 new PluginPackageImpl(
137                     artifactGroupId + StringPool.SLASH + artifactId +
138                         StringPool.SLASH + version + StringPool.SLASH +
139                             "war");
140 
141             pluginPackage.setName(artifactId);
142 
143             String shortDescription = attributes.getValue("Bundle-Description");
144 
145             if (Validator.isNotNull(shortDescription)) {
146                 pluginPackage.setShortDescription(shortDescription);
147             }
148 
149             String pageURL = attributes.getValue("Bundle-DocURL");
150 
151             if (Validator.isNotNull(pageURL)) {
152                 pluginPackage.setPageURL(pageURL);
153             }
154         }
155         else {
156             if (_log.isDebugEnabled()) {
157                 _log.debug(
158                     "Reading plugin package from liferay-plugin-package.xml");
159             }
160 
161             pluginPackage = PluginPackageUtil.readPluginPackageXml(xml);
162         }
163 
164         pluginPackage.setContext(servletContextName);
165 
166         return pluginPackage;
167     }
168 
169     public void invokeDeploy(HotDeployEvent event) throws HotDeployException {
170         try {
171             doInvokeDeploy(event);
172         }
173         catch (Exception e) {
174             throwHotDeployException(event, "Error registering plugins for ", e);
175         }
176     }
177 
178     public void invokeUndeploy(HotDeployEvent event) throws HotDeployException {
179         try {
180             doInvokeUndeploy(event);
181         }
182         catch (Exception e) {
183             throwHotDeployException(
184                 event, "Error unregistering plugins for ", e);
185         }
186     }
187 
188     protected void doInvokeDeploy(HotDeployEvent event) throws Exception {
189         ServletContext servletContext = event.getServletContext();
190 
191         String servletContextName = servletContext.getServletContextName();
192 
193         if (_log.isDebugEnabled()) {
194             _log.debug("Invoking deploy for " + servletContextName);
195         }
196 
197         if (servletContext.getResource(
198                 "/WEB-INF/liferay-theme-loader.xml") != null) {
199 
200             return;
201         }
202 
203         PluginPackage pluginPackage = readPluginPackage(servletContext);
204 
205         if (pluginPackage == null) {
206             return;
207         }
208 
209         pluginPackage.setContext(servletContextName);
210 
211         event.setPluginPackage(pluginPackage);
212 
213         PluginPackageUtil.registerInstalledPluginPackage(pluginPackage);
214 
215         _processServiceBuilderProperties = false;
216 
217         processServiceBuilderProperties(
218             servletContext, event.getContextClassLoader());
219 
220         if (_log.isInfoEnabled()) {
221             _log.info(
222                 "Plugin package " + pluginPackage.getModuleId() +
223                     " registered successfully");
224         }
225     }
226 
227     protected void doInvokeUndeploy(HotDeployEvent event) throws Exception {
228         ServletContext servletContext = event.getServletContext();
229 
230         String servletContextName = servletContext.getServletContextName();
231 
232         if (_log.isDebugEnabled()) {
233             _log.debug("Invoking deploy for " + servletContextName);
234         }
235 
236         PluginPackage pluginPackage = readPluginPackage(servletContext);
237 
238         if (pluginPackage == null) {
239             return;
240         }
241 
242         event.setPluginPackage(pluginPackage);
243 
244         PluginPackageUtil.unregisterInstalledPluginPackage(pluginPackage);
245 
246         PortletBeanLocatorUtil.setBeanLocator(servletContextName, null);
247 
248         if (_processServiceBuilderProperties) {
249             CacheRegistry.clear();
250         }
251 
252         if (_log.isInfoEnabled()) {
253             _log.info(
254                 "Plugin package " + pluginPackage.getModuleId() +
255                     " unregistered successfully");
256         }
257     }
258 
259     protected void processServiceBuilderProperties(
260             ServletContext servletContext, ClassLoader classLoader)
261         throws Exception {
262 
263         Configuration serviceBuilderPropertiesConfiguration = null;
264 
265         try {
266             serviceBuilderPropertiesConfiguration =
267                 ConfigurationFactoryUtil.getConfiguration(
268                     classLoader, "service");
269         }
270         catch (Exception e) {
271             if (_log.isDebugEnabled()) {
272                 _log.debug("Unable to read service.properties");
273             }
274         }
275 
276         if (serviceBuilderPropertiesConfiguration == null) {
277             return;
278         }
279 
280         Properties serviceBuilderProperties =
281             serviceBuilderPropertiesConfiguration.getProperties();
282 
283         if (serviceBuilderProperties.size() == 0) {
284             return;
285         }
286 
287         String buildNamespace = GetterUtil.getString(
288             serviceBuilderProperties.getProperty("build.namespace"));
289         long buildNumber = GetterUtil.getLong(
290             serviceBuilderProperties.getProperty("build.number"));
291         long buildDate = GetterUtil.getLong(
292             serviceBuilderProperties.getProperty("build.date"));
293 
294         if (_log.isDebugEnabled()) {
295             _log.debug("Build namespace " + buildNamespace);
296             _log.debug("Build number " + buildNumber);
297             _log.debug("Build date " + buildDate);
298         }
299 
300         ServiceComponentLocalServiceUtil.updateServiceComponent(
301             servletContext, classLoader, buildNamespace, buildNumber,
302             buildDate);
303 
304         _processServiceBuilderProperties = true;
305     }
306 
307     private static Log _log =
308         LogFactory.getLog(PluginPackageHotDeployListener.class);
309 
310     private boolean _processServiceBuilderProperties;
311 
312 }