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