1   /**
2    * Copyright (c) 2000-2009 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.configuration.Configuration;
26  import com.liferay.portal.kernel.configuration.ConfigurationFactoryUtil;
27  import com.liferay.portal.kernel.deploy.hot.HotDeployEvent;
28  import com.liferay.portal.kernel.deploy.hot.HotDeployException;
29  import com.liferay.portal.kernel.log.Log;
30  import com.liferay.portal.kernel.log.LogFactoryUtil;
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.kernel.xml.DocumentException;
37  import com.liferay.portal.plugin.PluginPackageImpl;
38  import com.liferay.portal.plugin.PluginPackageUtil;
39  import com.liferay.portal.service.ServiceComponentLocalServiceUtil;
40  import com.liferay.util.Version;
41  
42  import java.io.IOException;
43  import java.io.InputStream;
44  
45  import java.util.Properties;
46  import java.util.jar.Attributes;
47  import java.util.jar.Manifest;
48  
49  import javax.servlet.ServletContext;
50  
51  /**
52   * <a href="PluginPackageHotDeployListener.java.html"><b><i>View Source</i></b>
53   * </a>
54   *
55   * @author Jorge Ferrer
56   *
57   */
58  public class PluginPackageHotDeployListener extends BaseHotDeployListener {
59  
60      public static PluginPackage readPluginPackage(ServletContext servletContext)
61          throws DocumentException, IOException {
62  
63          PluginPackage pluginPackage = null;
64  
65          String servletContextName = servletContext.getServletContextName();
66  
67          String xml = HttpUtil.URLtoString(
68              servletContext.getResource("/WEB-INF/liferay-plugin-package.xml"));
69  
70          if (_log.isInfoEnabled()) {
71              if (servletContextName == null) {
72                  _log.info("Reading plugin package for the root context");
73              }
74              else {
75                  _log.info("Reading plugin package for " + servletContextName);
76              }
77          }
78  
79          if (xml == null) {
80              if (_log.isDebugEnabled()) {
81                  _log.debug("Reading plugin package from MANIFEST.MF");
82              }
83  
84              Attributes attributes = null;
85  
86              InputStream is = servletContext.getResourceAsStream(
87                  "/META-INF/MANIFEST.MF");
88  
89              if (is != null) {
90                  Manifest manifest = new Manifest(is);
91  
92                  attributes = manifest.getMainAttributes();
93              }
94              else {
95                  attributes = new Attributes();
96              }
97  
98              String artifactGroupId = attributes.getValue(
99                  "Implementation-Vendor-Id");
100 
101             if (Validator.isNull(artifactGroupId)) {
102                 artifactGroupId = attributes.getValue("Implementation-Vendor");
103             }
104 
105             if (Validator.isNull(artifactGroupId)) {
106                 artifactGroupId = GetterUtil.getString(
107                     attributes.getValue("Bundle-Vendor"), servletContextName);
108             }
109 
110             String artifactId = attributes.getValue("Implementation-Title");
111 
112             if (Validator.isNull(artifactId)) {
113                 artifactId = GetterUtil.getString(
114                     attributes.getValue("Bundle-Name"), servletContextName);
115             }
116 
117             String version = attributes.getValue("Implementation-Version");
118 
119             if (Validator.isNull(version)) {
120                 version = GetterUtil.getString(
121                     attributes.getValue("Bundle-Version"), Version.UNKNOWN);
122             }
123 
124             if (version.equals(Version.UNKNOWN) && _log.isWarnEnabled()) {
125                 _log.warn(
126                     "Plugin package on context " + servletContextName +
127                         " cannot be tracked because this WAR does not " +
128                             "contain a liferay-plugin-package.xml file");
129             }
130 
131             pluginPackage =
132                 new PluginPackageImpl(
133                     artifactGroupId + StringPool.SLASH + artifactId +
134                         StringPool.SLASH + version + StringPool.SLASH +
135                             "war");
136 
137             pluginPackage.setName(artifactId);
138 
139             String shortDescription = attributes.getValue("Bundle-Description");
140 
141             if (Validator.isNotNull(shortDescription)) {
142                 pluginPackage.setShortDescription(shortDescription);
143             }
144 
145             String pageURL = attributes.getValue("Bundle-DocURL");
146 
147             if (Validator.isNotNull(pageURL)) {
148                 pluginPackage.setPageURL(pageURL);
149             }
150         }
151         else {
152             if (_log.isDebugEnabled()) {
153                 _log.debug(
154                     "Reading plugin package from liferay-plugin-package.xml");
155             }
156 
157             pluginPackage = PluginPackageUtil.readPluginPackageXml(xml);
158         }
159 
160         pluginPackage.setContext(servletContextName);
161 
162         return pluginPackage;
163     }
164 
165     public void invokeDeploy(HotDeployEvent event) throws HotDeployException {
166         try {
167             doInvokeDeploy(event);
168         }
169         catch (Exception e) {
170             throwHotDeployException(event, "Error registering plugins for ", e);
171         }
172     }
173 
174     public void invokeUndeploy(HotDeployEvent event) throws HotDeployException {
175         try {
176             doInvokeUndeploy(event);
177         }
178         catch (Exception e) {
179             throwHotDeployException(
180                 event, "Error unregistering plugins for ", e);
181         }
182     }
183 
184     protected void destroyServiceComponent(
185             ServletContext servletContext, ClassLoader classLoader)
186         throws Exception {
187 
188         ServiceComponentLocalServiceUtil.destroyServiceComponent(
189             servletContext, classLoader);
190     }
191 
192     protected void doInvokeDeploy(HotDeployEvent event) throws Exception {
193         ServletContext servletContext = event.getServletContext();
194 
195         String servletContextName = servletContext.getServletContextName();
196 
197         if (_log.isDebugEnabled()) {
198             _log.debug("Invoking deploy for " + servletContextName);
199         }
200 
201         if (servletContext.getResource(
202                 "/WEB-INF/liferay-theme-loader.xml") != null) {
203 
204             return;
205         }
206 
207         PluginPackage pluginPackage = readPluginPackage(servletContext);
208 
209         if (pluginPackage == null) {
210             return;
211         }
212 
213         pluginPackage.setContext(servletContextName);
214 
215         event.setPluginPackage(pluginPackage);
216 
217         PluginPackageUtil.registerInstalledPluginPackage(pluginPackage);
218 
219         initServiceComponent(servletContext, event.getContextClassLoader());
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         destroyServiceComponent(servletContext, event.getContextClassLoader());
248 
249         if (_log.isInfoEnabled()) {
250             _log.info(
251                 "Plugin package " + pluginPackage.getModuleId() +
252                     " unregistered successfully");
253         }
254     }
255 
256     protected void initServiceComponent(
257             ServletContext servletContext, ClassLoader classLoader)
258         throws Exception {
259 
260         Configuration serviceBuilderPropertiesConfiguration = null;
261 
262         try {
263             serviceBuilderPropertiesConfiguration =
264                 ConfigurationFactoryUtil.getConfiguration(
265                     classLoader, "service");
266         }
267         catch (Exception e) {
268             if (_log.isDebugEnabled()) {
269                 _log.debug("Unable to read service.properties");
270             }
271 
272             return;
273         }
274 
275         Properties serviceBuilderProperties =
276             serviceBuilderPropertiesConfiguration.getProperties();
277 
278         if (serviceBuilderProperties.size() == 0) {
279             return;
280         }
281 
282         String buildNamespace = GetterUtil.getString(
283             serviceBuilderProperties.getProperty("build.namespace"));
284         long buildNumber = GetterUtil.getLong(
285             serviceBuilderProperties.getProperty("build.number"));
286         long buildDate = GetterUtil.getLong(
287             serviceBuilderProperties.getProperty("build.date"));
288 
289         if (_log.isDebugEnabled()) {
290             _log.debug("Build namespace " + buildNamespace);
291             _log.debug("Build number " + buildNumber);
292             _log.debug("Build date " + buildDate);
293         }
294 
295         ServiceComponentLocalServiceUtil.initServiceComponent(
296             servletContext, classLoader, buildNamespace, buildNumber,
297             buildDate);
298     }
299 
300     private static Log _log =
301         LogFactoryUtil.getLog(PluginPackageHotDeployListener.class);
302 
303 }