1   /**
2    * Copyright (c) 2000-2009 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   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
12   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
13   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
14   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
15   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
16   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
17   * SOFTWARE.
18   */
19  
20  package com.liferay.portal.deploy.hot;
21  
22  import com.liferay.portal.kernel.configuration.Configuration;
23  import com.liferay.portal.kernel.configuration.ConfigurationFactoryUtil;
24  import com.liferay.portal.kernel.deploy.hot.HotDeployEvent;
25  import com.liferay.portal.kernel.deploy.hot.HotDeployException;
26  import com.liferay.portal.kernel.log.Log;
27  import com.liferay.portal.kernel.log.LogFactoryUtil;
28  import com.liferay.portal.kernel.plugin.PluginPackage;
29  import com.liferay.portal.kernel.util.GetterUtil;
30  import com.liferay.portal.kernel.util.HttpUtil;
31  import com.liferay.portal.kernel.util.StringPool;
32  import com.liferay.portal.kernel.util.Validator;
33  import com.liferay.portal.kernel.xml.DocumentException;
34  import com.liferay.portal.plugin.PluginPackageImpl;
35  import com.liferay.portal.plugin.PluginPackageUtil;
36  import com.liferay.portal.service.ServiceComponentLocalServiceUtil;
37  import com.liferay.util.Version;
38  
39  import java.io.IOException;
40  import java.io.InputStream;
41  
42  import java.util.Properties;
43  import java.util.jar.Attributes;
44  import java.util.jar.Manifest;
45  
46  import javax.servlet.ServletContext;
47  
48  /**
49   * <a href="PluginPackageHotDeployListener.java.html"><b><i>View Source</i></b>
50   * </a>
51   *
52   * @author Jorge Ferrer
53   *
54   */
55  public class PluginPackageHotDeployListener extends BaseHotDeployListener {
56  
57      public static PluginPackage readPluginPackage(ServletContext servletContext)
58          throws DocumentException, IOException {
59  
60          PluginPackage pluginPackage = null;
61  
62          String servletContextName = servletContext.getServletContextName();
63  
64          String xml = HttpUtil.URLtoString(
65              servletContext.getResource("/WEB-INF/liferay-plugin-package.xml"));
66  
67          if (_log.isInfoEnabled()) {
68              if (servletContextName == null) {
69                  _log.info("Reading plugin package for the root context");
70              }
71              else {
72                  _log.info("Reading plugin package for " + servletContextName);
73              }
74          }
75  
76          if (xml == null) {
77              if (_log.isDebugEnabled()) {
78                  _log.debug("Reading plugin package from MANIFEST.MF");
79              }
80  
81              Attributes attributes = null;
82  
83              InputStream is = servletContext.getResourceAsStream(
84                  "/META-INF/MANIFEST.MF");
85  
86              if (is != null) {
87                  Manifest manifest = new Manifest(is);
88  
89                  attributes = manifest.getMainAttributes();
90              }
91              else {
92                  attributes = new Attributes();
93              }
94  
95              String artifactGroupId = attributes.getValue(
96                  "Implementation-Vendor-Id");
97  
98              if (Validator.isNull(artifactGroupId)) {
99                  artifactGroupId = attributes.getValue("Implementation-Vendor");
100             }
101 
102             if (Validator.isNull(artifactGroupId)) {
103                 artifactGroupId = GetterUtil.getString(
104                     attributes.getValue("Bundle-Vendor"), servletContextName);
105             }
106 
107             String artifactId = attributes.getValue("Implementation-Title");
108 
109             if (Validator.isNull(artifactId)) {
110                 artifactId = GetterUtil.getString(
111                     attributes.getValue("Bundle-Name"), servletContextName);
112             }
113 
114             String version = attributes.getValue("Implementation-Version");
115 
116             if (Validator.isNull(version)) {
117                 version = GetterUtil.getString(
118                     attributes.getValue("Bundle-Version"), Version.UNKNOWN);
119             }
120 
121             if (version.equals(Version.UNKNOWN) && _log.isWarnEnabled()) {
122                 _log.warn(
123                     "Plugin package on context " + servletContextName +
124                         " cannot be tracked because this WAR does not " +
125                             "contain a liferay-plugin-package.xml file");
126             }
127 
128             pluginPackage =
129                 new PluginPackageImpl(
130                     artifactGroupId + StringPool.SLASH + artifactId +
131                         StringPool.SLASH + version + StringPool.SLASH +
132                             "war");
133 
134             pluginPackage.setName(artifactId);
135 
136             String shortDescription = attributes.getValue("Bundle-Description");
137 
138             if (Validator.isNotNull(shortDescription)) {
139                 pluginPackage.setShortDescription(shortDescription);
140             }
141 
142             String pageURL = attributes.getValue("Bundle-DocURL");
143 
144             if (Validator.isNotNull(pageURL)) {
145                 pluginPackage.setPageURL(pageURL);
146             }
147         }
148         else {
149             if (_log.isDebugEnabled()) {
150                 _log.debug(
151                     "Reading plugin package from liferay-plugin-package.xml");
152             }
153 
154             pluginPackage = PluginPackageUtil.readPluginPackageXml(xml);
155         }
156 
157         pluginPackage.setContext(servletContextName);
158 
159         return pluginPackage;
160     }
161 
162     public void invokeDeploy(HotDeployEvent event) throws HotDeployException {
163         try {
164             doInvokeDeploy(event);
165         }
166         catch (Throwable t) {
167             throwHotDeployException(event, "Error registering plugins for ", t);
168         }
169     }
170 
171     public void invokeUndeploy(HotDeployEvent event) throws HotDeployException {
172         try {
173             doInvokeUndeploy(event);
174         }
175         catch (Throwable t) {
176             throwHotDeployException(
177                 event, "Error unregistering plugins for ", t);
178         }
179     }
180 
181     protected void destroyServiceComponent(
182             ServletContext servletContext, ClassLoader classLoader)
183         throws Exception {
184 
185         ServiceComponentLocalServiceUtil.destroyServiceComponent(
186             servletContext, classLoader);
187     }
188 
189     protected void doInvokeDeploy(HotDeployEvent event) throws Exception {
190         ServletContext servletContext = event.getServletContext();
191 
192         String servletContextName = servletContext.getServletContextName();
193 
194         if (_log.isDebugEnabled()) {
195             _log.debug("Invoking deploy for " + servletContextName);
196         }
197 
198         if (servletContext.getResource(
199                 "/WEB-INF/liferay-theme-loader.xml") != null) {
200 
201             return;
202         }
203 
204         PluginPackage pluginPackage = readPluginPackage(servletContext);
205 
206         if (pluginPackage == null) {
207             return;
208         }
209 
210         pluginPackage.setContext(servletContextName);
211 
212         event.setPluginPackage(pluginPackage);
213 
214         PluginPackageUtil.registerInstalledPluginPackage(pluginPackage);
215 
216         ClassLoader portletClassLoader = event.getContextClassLoader();
217 
218         initServiceComponent(servletContext, portletClassLoader);
219 
220         registerClpMessageListeners(servletContext, portletClassLoader);
221 
222         if (_log.isInfoEnabled()) {
223             _log.info(
224                 "Plugin package " + pluginPackage.getModuleId() +
225                     " registered successfully. It's now ready to be used.");
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         unregisterClpMessageListeners(servletContext);
251 
252         if (_log.isInfoEnabled()) {
253             _log.info(
254                 "Plugin package " + pluginPackage.getModuleId() +
255                     " unregistered successfully");
256         }
257     }
258 
259     protected void initServiceComponent(
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             return;
276         }
277 
278         Properties serviceBuilderProperties =
279             serviceBuilderPropertiesConfiguration.getProperties();
280 
281         if (serviceBuilderProperties.size() == 0) {
282             return;
283         }
284 
285         String buildNamespace = GetterUtil.getString(
286             serviceBuilderProperties.getProperty("build.namespace"));
287         long buildNumber = GetterUtil.getLong(
288             serviceBuilderProperties.getProperty("build.number"));
289         long buildDate = GetterUtil.getLong(
290             serviceBuilderProperties.getProperty("build.date"));
291         boolean buildAutoUpgrade = GetterUtil.getBoolean(
292             serviceBuilderProperties.getProperty("build.auto.upgrade"), true);
293 
294         if (_log.isDebugEnabled()) {
295             _log.debug("Build namespace " + buildNamespace);
296             _log.debug("Build number " + buildNumber);
297             _log.debug("Build date " + buildDate);
298             _log.debug("Build auto upgrade " + buildAutoUpgrade);
299         }
300 
301         if (Validator.isNull(buildNamespace)) {
302             return;
303         }
304 
305         ServiceComponentLocalServiceUtil.initServiceComponent(
306             servletContext, classLoader, buildNamespace, buildNumber,
307             buildDate, buildAutoUpgrade);
308     }
309 
310     private static Log _log =
311         LogFactoryUtil.getLog(PluginPackageHotDeployListener.class);
312 
313 }