1   /**
2    * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
3    *
4    * This library is free software; you can redistribute it and/or modify it under
5    * the terms of the GNU Lesser General Public License as published by the Free
6    * Software Foundation; either version 2.1 of the License, or (at your option)
7    * any later version.
8    *
9    * This library is distributed in the hope that it will be useful, but WITHOUT
10   * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
11   * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
12   * details.
13   */
14  
15  package com.liferay.portal.deploy.hot;
16  
17  import com.liferay.portal.kernel.deploy.hot.BaseHotDeployListener;
18  import com.liferay.portal.kernel.deploy.hot.HotDeployEvent;
19  import com.liferay.portal.kernel.deploy.hot.HotDeployException;
20  import com.liferay.portal.kernel.log.Log;
21  import com.liferay.portal.kernel.log.LogFactoryUtil;
22  import com.liferay.portal.kernel.servlet.WebDirDetector;
23  import com.liferay.portal.kernel.util.FileUtil;
24  import com.liferay.portal.kernel.util.HttpUtil;
25  import com.liferay.portal.kernel.util.StreamUtil;
26  import com.liferay.portal.kernel.util.StringBundler;
27  import com.liferay.portal.kernel.util.StringPool;
28  import com.liferay.portal.kernel.util.Time;
29  import com.liferay.portal.tools.WebXMLBuilder;
30  import com.liferay.portal.util.ExtRegistry;
31  import com.liferay.portal.util.PortalUtil;
32  import com.liferay.util.SystemProperties;
33  import com.liferay.util.ant.CopyTask;
34  
35  import java.io.File;
36  import java.io.FileOutputStream;
37  import java.io.InputStream;
38  
39  import java.util.Iterator;
40  import java.util.Map;
41  import java.util.Set;
42  
43  import javax.servlet.ServletContext;
44  
45  /**
46   * <a href="ExtHotDeployListener.java.html"><b><i>View Source</i></b></a>
47   *
48   * @author Brian Wing Shun Chan
49   */
50  public class ExtHotDeployListener extends BaseHotDeployListener {
51  
52      public void invokeDeploy(HotDeployEvent event) throws HotDeployException {
53          try {
54              doInvokeDeploy(event);
55          }
56          catch (Throwable t) {
57              throwHotDeployException(
58                  event, "Error registering extension environment for ", t);
59          }
60      }
61  
62      public void invokeUndeploy(HotDeployEvent event) throws HotDeployException {
63          try {
64              doInvokeUndeploy(event);
65          }
66          catch (Throwable t) {
67              throwHotDeployException(
68                  event, "Error unregistering extension environment for ", t);
69          }
70      }
71  
72      protected void copyJar(
73              ServletContext servletContext, String dir, String jarName)
74          throws Exception {
75  
76          String servletContextName = servletContext.getServletContextName();
77  
78          String jarFullName = "/WEB-INF/" + jarName + "/" + jarName + ".jar";
79  
80          InputStream is = servletContext.getResourceAsStream(jarFullName);
81  
82          if (is == null) {
83              throw new HotDeployException(jarFullName + " does not exist");
84          }
85  
86          String newJarFullName =
87              dir + "ext-" + servletContextName + jarName.substring(3) + ".jar";
88  
89          StreamUtil.transfer(is, new FileOutputStream(new File(newJarFullName)));
90      }
91  
92      protected void installExt(
93              ServletContext servletContext, ClassLoader portletClassLoader)
94          throws Exception {
95  
96          String servletContextName = servletContext.getServletContextName();
97  
98          String globalLibDir = PortalUtil.getGlobalLibDir();
99          String portalWebDir = PortalUtil.getPortalWebDir();
100         String portalLibDir = PortalUtil.getPortalLibDir();
101         String pluginWebDir = WebDirDetector.getRootDir(portletClassLoader);
102 
103         copyJar(servletContext, globalLibDir, "ext-service");
104         copyJar(servletContext, portalLibDir, "ext-impl");
105         copyJar(servletContext, portalLibDir, "ext-util-bridges");
106         copyJar(servletContext, portalLibDir, "ext-util-java");
107         copyJar(servletContext, portalLibDir, "ext-util-taglib");
108 
109         mergeWebXml(portalWebDir, pluginWebDir);
110 
111         CopyTask.copyDirectory(
112             pluginWebDir + "WEB-INF/ext-web/docroot", portalWebDir,
113             StringPool.BLANK, "**/WEB-INF/web.xml", true, false);
114 
115         FileUtil.copyFile(
116             pluginWebDir + "WEB-INF/ext-" + servletContextName + ".xml",
117             portalWebDir + "WEB-INF/ext-" + servletContextName + ".xml");
118 
119         ExtRegistry.registerExt(servletContext);
120     }
121 
122     protected void doInvokeDeploy(HotDeployEvent event) throws Exception {
123         ServletContext servletContext = event.getServletContext();
124 
125         String servletContextName = servletContext.getServletContextName();
126 
127         if (_log.isDebugEnabled()) {
128             _log.debug("Invoking deploy for " + servletContextName);
129         }
130 
131         String xml = HttpUtil.URLtoString(servletContext.getResource(
132             "/WEB-INF/ext-" + servletContextName + ".xml"));
133 
134         if (xml == null) {
135             return;
136         }
137 
138         if (_log.isInfoEnabled()) {
139             _log.info(
140                 "Registering extension environment for " + servletContextName);
141         }
142 
143         if (ExtRegistry.isRegistered(servletContextName)) {
144             if (_log.isInfoEnabled()) {
145                 _log.info(
146                     "Extension environment for " + servletContextName +
147                         " has been applied.");
148             }
149 
150             return;
151         }
152 
153         Map<String, Set<String>> conflicts = ExtRegistry.getConflicts(
154             servletContext);
155 
156         if (!conflicts.isEmpty()) {
157             StringBundler sb = new StringBundler();
158 
159             sb.append(
160                 "Extension environment for " + servletContextName +
161                     " cannot be applied because of detected conflicts:");
162 
163             Iterator<Map.Entry<String, Set<String>>> itr =
164                 conflicts.entrySet().iterator();
165 
166             while (itr.hasNext()) {
167                 Map.Entry<String, Set<String>> entry = itr.next();
168 
169                 String conflictServletContextName = entry.getKey();
170                 Set<String> conflictFiles = entry.getValue();
171 
172                 sb.append("\n\t");
173                 sb.append(conflictServletContextName);
174                 sb.append(":");
175 
176                 for (String conflictFile : conflictFiles) {
177                     sb.append("\n\t\t");
178                     sb.append(conflictFile);
179                 }
180             }
181 
182             _log.error(sb.toString());
183 
184             return;
185         }
186 
187         installExt(servletContext, event.getContextClassLoader());
188 
189         if (_log.isInfoEnabled()) {
190             _log.info(
191                 "Extension environment for " + servletContextName +
192                     " has been applied. You must reboot the server and " +
193                         "redeploy all other plugins.");
194         }
195     }
196 
197     protected void doInvokeUndeploy(HotDeployEvent event) throws Exception {
198         ServletContext servletContext = event.getServletContext();
199 
200         String servletContextName = servletContext.getServletContextName();
201 
202         if (_log.isDebugEnabled()) {
203             _log.debug("Invoking undeploy for " + servletContextName);
204         }
205 
206         if (_log.isInfoEnabled()) {
207             _log.info(
208                 "Extension environment for " +
209                     servletContextName + " will not be undeployed");
210         }
211     }
212 
213     protected void mergeWebXml(String portalWebDir, String pluginWebDir) {
214         if (!FileUtil.exists(
215                 pluginWebDir + "WEB-INF/ext-web/docroot/WEB-INF/web.xml")) {
216 
217             return;
218         }
219 
220         String tmpDir =
221             SystemProperties.get(SystemProperties.TMP_DIR) + StringPool.SLASH +
222                 Time.getTimestamp();
223 
224         WebXMLBuilder.main(
225             new String[] {
226                 portalWebDir + "WEB-INF/web.xml",
227                 pluginWebDir + "WEB-INF/ext-web/docroot/WEB-INF/web.xml",
228                 tmpDir + "/web.xml"
229             });
230 
231         File portalWebXml = new File(portalWebDir + "WEB-INF/web.xml");
232         File tmpWebXml = new File(tmpDir + "/web.xml");
233 
234         tmpWebXml.setLastModified(portalWebXml.lastModified());
235 
236         CopyTask.copyFile(
237             tmpWebXml, new File(portalWebDir + "WEB-INF"), true, true);
238 
239         FileUtil.deltree(tmpDir);
240     }
241 
242     private static Log _log = LogFactoryUtil.getLog(ExtHotDeployListener.class);
243 
244 }