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