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.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(
132             servletContext.getResource(
133                 "/WEB-INF/ext-" + servletContextName + ".xml"));
134 
135         if (xml == null) {
136             return;
137         }
138 
139         if (_log.isInfoEnabled()) {
140             _log.info(
141                 "Registering extension environment for " + servletContextName);
142         }
143 
144         if (ExtRegistry.isRegistered(servletContextName)) {
145             if (_log.isInfoEnabled()) {
146                 _log.info(
147                     "Extension environment for " + servletContextName +
148                         " has been applied.");
149             }
150 
151             return;
152         }
153 
154         Map<String, Set<String>> conflicts = ExtRegistry.getConflicts(
155             servletContext);
156 
157         if (!conflicts.isEmpty()) {
158             StringBundler sb = new StringBundler();
159 
160             sb.append(
161                 "Extension environment for " + servletContextName +
162                     " cannot be applied because of detected conflicts:");
163 
164             Iterator<Map.Entry<String, Set<String>>> itr =
165                 conflicts.entrySet().iterator();
166 
167             while (itr.hasNext()) {
168                 Map.Entry<String, Set<String>> entry = itr.next();
169 
170                 String conflictServletContextName = entry.getKey();
171                 Set<String> conflictFiles = entry.getValue();
172 
173                 sb.append("\n\t");
174                 sb.append(conflictServletContextName);
175                 sb.append(":");
176 
177                 for (String conflictFile : conflictFiles) {
178                     sb.append("\n\t\t");
179                     sb.append(conflictFile);
180                 }
181             }
182 
183             _log.error(sb.toString());
184 
185             return;
186         }
187 
188         installExt(servletContext, event.getContextClassLoader());
189 
190         if (_log.isInfoEnabled()) {
191             _log.info(
192                 "Extension environment for " + servletContextName +
193                     " has been applied. You must reboot the server and " +
194                         "redeploy all other plugins.");
195         }
196     }
197 
198     protected void doInvokeUndeploy(HotDeployEvent event) throws Exception {
199         ServletContext servletContext = event.getServletContext();
200 
201         String servletContextName = servletContext.getServletContextName();
202 
203         if (_log.isDebugEnabled()) {
204             _log.debug("Invoking undeploy for " + servletContextName);
205         }
206 
207         String xml = HttpUtil.URLtoString(
208             servletContext.getResource(
209                 "/WEB-INF/ext-" + servletContextName + ".xml"));
210 
211         if (xml == null) {
212             return;
213         }
214 
215         if (_log.isInfoEnabled()) {
216             _log.info(
217                 "Extension environment for " +
218                     servletContextName + " will not be undeployed");
219         }
220     }
221 
222     protected void mergeWebXml(String portalWebDir, String pluginWebDir) {
223         if (!FileUtil.exists(
224                 pluginWebDir + "WEB-INF/ext-web/docroot/WEB-INF/web.xml")) {
225 
226             return;
227         }
228 
229         String tmpDir =
230             SystemProperties.get(SystemProperties.TMP_DIR) + StringPool.SLASH +
231                 Time.getTimestamp();
232 
233         WebXMLBuilder.main(
234             new String[] {
235                 portalWebDir + "WEB-INF/web.xml",
236                 pluginWebDir + "WEB-INF/ext-web/docroot/WEB-INF/web.xml",
237                 tmpDir + "/web.xml"
238             });
239 
240         File portalWebXml = new File(portalWebDir + "WEB-INF/web.xml");
241         File tmpWebXml = new File(tmpDir + "/web.xml");
242 
243         tmpWebXml.setLastModified(portalWebXml.lastModified());
244 
245         CopyTask.copyFile(
246             tmpWebXml, new File(portalWebDir + "WEB-INF"), true, true);
247 
248         FileUtil.deltree(tmpDir);
249     }
250 
251     private static Log _log = LogFactoryUtil.getLog(ExtHotDeployListener.class);
252 
253 }