001    /**
002     * Copyright (c) 2000-2010 Liferay, Inc. All rights reserved.
003     *
004     * This library is free software; you can redistribute it and/or modify it under
005     * the terms of the GNU Lesser General Public License as published by the Free
006     * Software Foundation; either version 2.1 of the License, or (at your option)
007     * any later version.
008     *
009     * This library is distributed in the hope that it will be useful, but WITHOUT
010     * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
011     * FOR A PARTICULAR PURPOSE. See the GNU Lesser General Public License for more
012     * details.
013     */
014    
015    package com.liferay.portal.deploy.hot;
016    
017    import com.liferay.portal.kernel.deploy.hot.BaseHotDeployListener;
018    import com.liferay.portal.kernel.deploy.hot.HotDeployEvent;
019    import com.liferay.portal.kernel.deploy.hot.HotDeployException;
020    import com.liferay.portal.kernel.log.Log;
021    import com.liferay.portal.kernel.log.LogFactoryUtil;
022    import com.liferay.portal.kernel.servlet.WebDirDetector;
023    import com.liferay.portal.kernel.util.FileUtil;
024    import com.liferay.portal.kernel.util.HttpUtil;
025    import com.liferay.portal.kernel.util.StreamUtil;
026    import com.liferay.portal.kernel.util.StringBundler;
027    import com.liferay.portal.kernel.util.StringPool;
028    import com.liferay.portal.kernel.util.Time;
029    import com.liferay.portal.tools.WebXMLBuilder;
030    import com.liferay.portal.util.ExtRegistry;
031    import com.liferay.portal.util.PortalUtil;
032    import com.liferay.util.SystemProperties;
033    import com.liferay.util.ant.CopyTask;
034    
035    import java.io.File;
036    import java.io.FileOutputStream;
037    import java.io.InputStream;
038    
039    import java.util.Iterator;
040    import java.util.Map;
041    import java.util.Set;
042    
043    import javax.servlet.ServletContext;
044    
045    /**
046     * @author Brian Wing Shun Chan
047     */
048    public class ExtHotDeployListener extends BaseHotDeployListener {
049    
050            public void invokeDeploy(HotDeployEvent event) throws HotDeployException {
051                    try {
052                            doInvokeDeploy(event);
053                    }
054                    catch (Throwable t) {
055                            throwHotDeployException(
056                                    event, "Error registering extension environment for ", t);
057                    }
058            }
059    
060            public void invokeUndeploy(HotDeployEvent event) throws HotDeployException {
061                    try {
062                            doInvokeUndeploy(event);
063                    }
064                    catch (Throwable t) {
065                            throwHotDeployException(
066                                    event, "Error unregistering extension environment for ", t);
067                    }
068            }
069    
070            protected void copyJar(
071                            ServletContext servletContext, String dir, String jarName)
072                    throws Exception {
073    
074                    String servletContextName = servletContext.getServletContextName();
075    
076                    String jarFullName = "/WEB-INF/" + jarName + "/" + jarName + ".jar";
077    
078                    InputStream is = servletContext.getResourceAsStream(jarFullName);
079    
080                    if (is == null) {
081                            throw new HotDeployException(jarFullName + " does not exist");
082                    }
083    
084                    String newJarFullName =
085                            dir + "ext-" + servletContextName + jarName.substring(3) + ".jar";
086    
087                    StreamUtil.transfer(is, new FileOutputStream(new File(newJarFullName)));
088            }
089    
090            protected void installExt(
091                            ServletContext servletContext, ClassLoader portletClassLoader)
092                    throws Exception {
093    
094                    String servletContextName = servletContext.getServletContextName();
095    
096                    String globalLibDir = PortalUtil.getGlobalLibDir();
097                    String portalWebDir = PortalUtil.getPortalWebDir();
098                    String portalLibDir = PortalUtil.getPortalLibDir();
099                    String pluginWebDir = WebDirDetector.getRootDir(portletClassLoader);
100    
101                    copyJar(servletContext, globalLibDir, "ext-service");
102                    copyJar(servletContext, portalLibDir, "ext-impl");
103                    copyJar(servletContext, portalLibDir, "ext-util-bridges");
104                    copyJar(servletContext, portalLibDir, "ext-util-java");
105                    copyJar(servletContext, portalLibDir, "ext-util-taglib");
106    
107                    mergeWebXml(portalWebDir, pluginWebDir);
108    
109                    CopyTask.copyDirectory(
110                            pluginWebDir + "WEB-INF/ext-web/docroot", portalWebDir,
111                            StringPool.BLANK, "**/WEB-INF/web.xml", true, false);
112    
113                    FileUtil.copyFile(
114                            pluginWebDir + "WEB-INF/ext-" + servletContextName + ".xml",
115                            portalWebDir + "WEB-INF/ext-" + servletContextName + ".xml");
116    
117                    ExtRegistry.registerExt(servletContext);
118            }
119    
120            protected void doInvokeDeploy(HotDeployEvent event) throws Exception {
121                    ServletContext servletContext = event.getServletContext();
122    
123                    String servletContextName = servletContext.getServletContextName();
124    
125                    if (_log.isDebugEnabled()) {
126                            _log.debug("Invoking deploy for " + servletContextName);
127                    }
128    
129                    String xml = HttpUtil.URLtoString(servletContext.getResource(
130                            "/WEB-INF/ext-" + servletContextName + ".xml"));
131    
132                    if (xml == null) {
133                            return;
134                    }
135    
136                    if (_log.isInfoEnabled()) {
137                            _log.info(
138                                    "Registering extension environment for " + servletContextName);
139                    }
140    
141                    if (ExtRegistry.isRegistered(servletContextName)) {
142                            if (_log.isInfoEnabled()) {
143                                    _log.info(
144                                            "Extension environment for " + servletContextName +
145                                                    " has been applied.");
146                            }
147    
148                            return;
149                    }
150    
151                    Map<String, Set<String>> conflicts = ExtRegistry.getConflicts(
152                            servletContext);
153    
154                    if (!conflicts.isEmpty()) {
155                            StringBundler sb = new StringBundler();
156    
157                            sb.append(
158                                    "Extension environment for " + servletContextName +
159                                            " cannot be applied because of detected conflicts:");
160    
161                            Iterator<Map.Entry<String, Set<String>>> itr =
162                                    conflicts.entrySet().iterator();
163    
164                            while (itr.hasNext()) {
165                                    Map.Entry<String, Set<String>> entry = itr.next();
166    
167                                    String conflictServletContextName = entry.getKey();
168                                    Set<String> conflictFiles = entry.getValue();
169    
170                                    sb.append("\n\t");
171                                    sb.append(conflictServletContextName);
172                                    sb.append(":");
173    
174                                    for (String conflictFile : conflictFiles) {
175                                            sb.append("\n\t\t");
176                                            sb.append(conflictFile);
177                                    }
178                            }
179    
180                            _log.error(sb.toString());
181    
182                            return;
183                    }
184    
185                    installExt(servletContext, event.getContextClassLoader());
186    
187                    if (_log.isInfoEnabled()) {
188                            _log.info(
189                                    "Extension environment for " + servletContextName +
190                                            " has been applied. You must reboot the server and " +
191                                                    "redeploy all other plugins.");
192                    }
193            }
194    
195            protected void doInvokeUndeploy(HotDeployEvent event) throws Exception {
196                    ServletContext servletContext = event.getServletContext();
197    
198                    String servletContextName = servletContext.getServletContextName();
199    
200                    if (_log.isDebugEnabled()) {
201                            _log.debug("Invoking undeploy for " + servletContextName);
202                    }
203    
204                    if (_log.isInfoEnabled()) {
205                            _log.info(
206                                    "Extension environment for " +
207                                            servletContextName + " will not be undeployed");
208                    }
209            }
210    
211            protected void mergeWebXml(String portalWebDir, String pluginWebDir) {
212                    if (!FileUtil.exists(
213                                    pluginWebDir + "WEB-INF/ext-web/docroot/WEB-INF/web.xml")) {
214    
215                            return;
216                    }
217    
218                    String tmpDir =
219                            SystemProperties.get(SystemProperties.TMP_DIR) + StringPool.SLASH +
220                                    Time.getTimestamp();
221    
222                    WebXMLBuilder.main(
223                            new String[] {
224                                    portalWebDir + "WEB-INF/web.xml",
225                                    pluginWebDir + "WEB-INF/ext-web/docroot/WEB-INF/web.xml",
226                                    tmpDir + "/web.xml"
227                            });
228    
229                    File portalWebXml = new File(portalWebDir + "WEB-INF/web.xml");
230                    File tmpWebXml = new File(tmpDir + "/web.xml");
231    
232                    tmpWebXml.setLastModified(portalWebXml.lastModified());
233    
234                    CopyTask.copyFile(
235                            tmpWebXml, new File(portalWebDir + "WEB-INF"), true, true);
236    
237                    FileUtil.deltree(tmpDir);
238            }
239    
240            private static Log _log = LogFactoryUtil.getLog(ExtHotDeployListener.class);
241    
242    }