1   /**
2    * Copyright (c) 2000-2009 Liferay, Inc. All rights reserved.
3    *
4    *
5    *
6    *
7    * The contents of this file are subject to the terms of the Liferay Enterprise
8    * Subscription License ("License"). You may not use this file except in
9    * compliance with the License. You can obtain a copy of the License by
10   * contacting Liferay, Inc. See the License for the specific language governing
11   * permissions and limitations under the License, including but not limited to
12   * distribution rights 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  public class PluginPackageHotDeployListener extends BaseHotDeployListener {
58  
59      public static PluginPackage readPluginPackage(ServletContext servletContext)
60          throws DocumentException, IOException {
61  
62          PluginPackage pluginPackage = null;
63  
64          String servletContextName = servletContext.getServletContextName();
65  
66          String xml = HttpUtil.URLtoString(
67              servletContext.getResource("/WEB-INF/liferay-plugin-package.xml"));
68  
69          if (_log.isInfoEnabled()) {
70              if (servletContextName == null) {
71                  _log.info("Reading plugin package for the root context");
72              }
73              else {
74                  _log.info("Reading plugin package for " + servletContextName);
75              }
76          }
77  
78          if (xml == null) {
79              if (_log.isDebugEnabled()) {
80                  _log.debug("Reading plugin package from MANIFEST.MF");
81              }
82  
83              Attributes attributes = null;
84  
85              InputStream is = servletContext.getResourceAsStream(
86                  "/META-INF/MANIFEST.MF");
87  
88              if (is != null) {
89                  Manifest manifest = new Manifest(is);
90  
91                  attributes = manifest.getMainAttributes();
92              }
93              else {
94                  attributes = new Attributes();
95              }
96  
97              String artifactGroupId = attributes.getValue(
98                  "Implementation-Vendor-Id");
99  
100             if (Validator.isNull(artifactGroupId)) {
101                 artifactGroupId = attributes.getValue("Implementation-Vendor");
102             }
103 
104             if (Validator.isNull(artifactGroupId)) {
105                 artifactGroupId = GetterUtil.getString(
106                     attributes.getValue("Bundle-Vendor"), servletContextName);
107             }
108 
109             String artifactId = attributes.getValue("Implementation-Title");
110 
111             if (Validator.isNull(artifactId)) {
112                 artifactId = GetterUtil.getString(
113                     attributes.getValue("Bundle-Name"), servletContextName);
114             }
115 
116             String version = attributes.getValue("Implementation-Version");
117 
118             if (Validator.isNull(version)) {
119                 version = GetterUtil.getString(
120                     attributes.getValue("Bundle-Version"), Version.UNKNOWN);
121             }
122 
123             if (version.equals(Version.UNKNOWN) && _log.isWarnEnabled()) {
124                 _log.warn(
125                     "Plugin package on context " + servletContextName +
126                         " cannot be tracked because this WAR does not " +
127                             "contain a liferay-plugin-package.xml file");
128             }
129 
130             pluginPackage =
131                 new PluginPackageImpl(
132                     artifactGroupId + StringPool.SLASH + artifactId +
133                         StringPool.SLASH + version + StringPool.SLASH +
134                             "war");
135 
136             pluginPackage.setName(artifactId);
137 
138             String shortDescription = attributes.getValue("Bundle-Description");
139 
140             if (Validator.isNotNull(shortDescription)) {
141                 pluginPackage.setShortDescription(shortDescription);
142             }
143 
144             String pageURL = attributes.getValue("Bundle-DocURL");
145 
146             if (Validator.isNotNull(pageURL)) {
147                 pluginPackage.setPageURL(pageURL);
148             }
149         }
150         else {
151             if (_log.isDebugEnabled()) {
152                 _log.debug(
153                     "Reading plugin package from liferay-plugin-package.xml");
154             }
155 
156             pluginPackage = PluginPackageUtil.readPluginPackageXml(xml);
157         }
158 
159         pluginPackage.setContext(servletContextName);
160 
161         return pluginPackage;
162     }
163 
164     public void invokeDeploy(HotDeployEvent event) throws HotDeployException {
165         try {
166             doInvokeDeploy(event);
167         }
168         catch (Throwable t) {
169             throwHotDeployException(event, "Error registering plugins for ", t);
170         }
171     }
172 
173     public void invokeUndeploy(HotDeployEvent event) throws HotDeployException {
174         try {
175             doInvokeUndeploy(event);
176         }
177         catch (Throwable t) {
178             throwHotDeployException(
179                 event, "Error unregistering plugins for ", t);
180         }
181     }
182 
183     protected void destroyServiceComponent(
184             ServletContext servletContext, ClassLoader classLoader)
185         throws Exception {
186 
187         ServiceComponentLocalServiceUtil.destroyServiceComponent(
188             servletContext, classLoader);
189     }
190 
191     protected void doInvokeDeploy(HotDeployEvent event) throws Exception {
192         ServletContext servletContext = event.getServletContext();
193 
194         String servletContextName = servletContext.getServletContextName();
195 
196         if (_log.isDebugEnabled()) {
197             _log.debug("Invoking deploy for " + servletContextName);
198         }
199 
200         if (servletContext.getResource(
201                 "/WEB-INF/liferay-theme-loader.xml") != null) {
202 
203             return;
204         }
205 
206         PluginPackage pluginPackage = readPluginPackage(servletContext);
207 
208         if (pluginPackage == null) {
209             return;
210         }
211 
212         pluginPackage.setContext(servletContextName);
213 
214         event.setPluginPackage(pluginPackage);
215 
216         PluginPackageUtil.registerInstalledPluginPackage(pluginPackage);
217 
218         ClassLoader portletClassLoader = event.getContextClassLoader();
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         destroyServiceComponent(servletContext, event.getContextClassLoader());
251 
252         unregisterClpMessageListeners(servletContext);
253 
254         if (_log.isInfoEnabled()) {
255             _log.info(
256                 "Plugin package " + pluginPackage.getModuleId() +
257                     " unregistered successfully");
258         }
259     }
260 
261     protected void initServiceComponent(
262             ServletContext servletContext, ClassLoader classLoader)
263         throws Exception {
264 
265         Configuration serviceBuilderPropertiesConfiguration = null;
266 
267         try {
268             serviceBuilderPropertiesConfiguration =
269                 ConfigurationFactoryUtil.getConfiguration(
270                     classLoader, "service");
271         }
272         catch (Exception e) {
273             if (_log.isDebugEnabled()) {
274                 _log.debug("Unable to read service.properties");
275             }
276 
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         boolean buildAutoUpgrade = GetterUtil.getBoolean(
294             serviceBuilderProperties.getProperty("build.auto.upgrade"), true);
295 
296         if (_log.isDebugEnabled()) {
297             _log.debug("Build namespace " + buildNamespace);
298             _log.debug("Build number " + buildNumber);
299             _log.debug("Build date " + buildDate);
300             _log.debug("Build auto upgrade " + buildAutoUpgrade);
301         }
302 
303         if (Validator.isNull(buildNamespace)) {
304             return;
305         }
306 
307         ServiceComponentLocalServiceUtil.initServiceComponent(
308             servletContext, classLoader, buildNamespace, buildNumber,
309             buildDate, buildAutoUpgrade);
310     }
311 
312     private static Log _log =
313         LogFactoryUtil.getLog(PluginPackageHotDeployListener.class);
314 
315 }