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