001    /**
002     * Copyright (c) 2000-2013 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.tools.deploy;
016    
017    import com.liferay.portal.kernel.plugin.PluginPackage;
018    import com.liferay.portal.kernel.util.FileUtil;
019    import com.liferay.portal.kernel.util.GetterUtil;
020    import com.liferay.portal.kernel.util.PropsKeys;
021    import com.liferay.portal.kernel.util.ServerDetector;
022    import com.liferay.portal.kernel.util.StringBundler;
023    import com.liferay.portal.kernel.util.StringUtil;
024    import com.liferay.portal.kernel.util.Validator;
025    import com.liferay.portal.kernel.xml.Document;
026    import com.liferay.portal.kernel.xml.Element;
027    import com.liferay.portal.kernel.xml.UnsecureSAXReaderUtil;
028    import com.liferay.portal.model.Plugin;
029    import com.liferay.portal.util.InitUtil;
030    import com.liferay.portal.util.Portal;
031    import com.liferay.portal.util.PortalUtil;
032    import com.liferay.portal.util.PrefsPropsUtil;
033    import com.liferay.portal.util.PropsValues;
034    import com.liferay.util.bridges.alloy.AlloyPortlet;
035    import com.liferay.util.bridges.mvc.MVCPortlet;
036    
037    import java.io.File;
038    
039    import java.util.ArrayList;
040    import java.util.List;
041    
042    /**
043     * @author Brian Wing Shun Chan
044     * @author Brian Myunghun Kim
045     */
046    public class PortletDeployer extends BaseDeployer {
047    
048            public static final String JSF_STANDARD =
049                    "javax.portlet.faces.GenericFacesPortlet";
050    
051            public static void main(String[] args) {
052                    InitUtil.initWithSpring();
053    
054                    List<String> wars = new ArrayList<String>();
055                    List<String> jars = new ArrayList<String>();
056    
057                    for (String arg : args) {
058                            if (arg.endsWith(".war")) {
059                                    wars.add(arg);
060                            }
061                            else if (arg.endsWith(".jar")) {
062                                    jars.add(arg);
063                            }
064                    }
065    
066                    new PortletDeployer(wars, jars);
067            }
068    
069            public PortletDeployer() {
070            }
071    
072            public PortletDeployer(List<String> wars, List<String> jars) {
073                    super(wars, jars);
074            }
075    
076            @Override
077            public void checkArguments() {
078                    super.checkArguments();
079    
080                    if (Validator.isNull(portletTaglibDTD)) {
081                            throw new IllegalArgumentException(
082                                    "The system property deployer.portlet.taglib.dtd is not set");
083                    }
084            }
085    
086            @Override
087            public void copyXmls(
088                            File srcFile, String displayName, PluginPackage pluginPackage)
089                    throws Exception {
090    
091                    super.copyXmls(srcFile, displayName, pluginPackage);
092    
093                    copyTomcatContextXml(srcFile);
094    
095                    copyDependencyXml(
096                            "_servlet_context_include.jsp", srcFile + "/WEB-INF/jsp");
097            }
098    
099            @Override
100            public String getExtraContent(
101                            double webXmlVersion, File srcFile, String displayName)
102                    throws Exception {
103    
104                    StringBundler sb = new StringBundler();
105    
106                    if (ServerDetector.isWebSphere()) {
107                            sb.append("<context-param>");
108                            sb.append("<param-name>");
109                            sb.append("com.ibm.websphere.portletcontainer.");
110                            sb.append("PortletDeploymentEnabled");
111                            sb.append("</param-name>");
112                            sb.append("<param-value>false</param-value>");
113                            sb.append("</context-param>");
114                    }
115    
116                    File portletXML = new File(
117                            srcFile + "/WEB-INF/" + Portal.PORTLET_XML_FILE_NAME_STANDARD);
118                    File webXML = new File(srcFile + "/WEB-INF/web.xml");
119    
120                    updatePortletXML(portletXML);
121    
122                    sb.append(getServletContent(portletXML, webXML));
123    
124                    setupAlloy(srcFile, portletXML);
125    
126                    String extraContent = super.getExtraContent(
127                            webXmlVersion, srcFile, displayName);
128    
129                    sb.append(extraContent);
130    
131                    return sb.toString();
132            }
133    
134            @Override
135            public String getExtraFiltersContent(double webXmlVersion, File srcFile)
136                    throws Exception {
137    
138                    StringBundler sb = new StringBundler(4);
139    
140                    String extraFiltersContent = super.getExtraFiltersContent(
141                            webXmlVersion, srcFile);
142    
143                    sb.append(extraFiltersContent);
144    
145                    // Ignore filters
146    
147                    sb.append(getIgnoreFiltersContent(srcFile));
148    
149                    // Speed filters
150    
151                    sb.append(getSpeedFiltersContent(srcFile));
152    
153                    // Servlet context include filters
154    
155                    sb.append(
156                            getServletContextIncludeFiltersContent(webXmlVersion, srcFile));
157    
158                    return sb.toString();
159            }
160    
161            @Override
162            public String getPluginType() {
163                    return Plugin.TYPE_PORTLET;
164            }
165    
166            public String getServletContent(File portletXML, File webXML)
167                    throws Exception {
168    
169                    StringBundler sb = new StringBundler();
170    
171                    Document document = UnsecureSAXReaderUtil.read(portletXML);
172    
173                    Element rootElement = document.getRootElement();
174    
175                    List<Element> portletElements = rootElement.elements("portlet");
176    
177                    for (Element portletElement : portletElements) {
178                            String portletName = PortalUtil.getJsSafePortletId(
179                                    portletElement.elementText("portlet-name"));
180                            String portletClassName = portletElement.elementText(
181                                    "portlet-class");
182    
183                            String servletName = portletName + " Servlet";
184    
185                            sb.append("<servlet>");
186                            sb.append("<servlet-name>");
187                            sb.append(servletName);
188                            sb.append("</servlet-name>");
189                            sb.append("<servlet-class>");
190                            sb.append("com.liferay.portal.kernel.servlet.PortletServlet");
191                            sb.append("</servlet-class>");
192                            sb.append("<init-param>");
193                            sb.append("<param-name>portlet-class</param-name>");
194                            sb.append("<param-value>");
195                            sb.append(portletClassName);
196                            sb.append("</param-value>");
197                            sb.append("</init-param>");
198                            sb.append("<load-on-startup>1</load-on-startup>");
199                            sb.append("</servlet>");
200    
201                            sb.append("<servlet-mapping>");
202                            sb.append("<servlet-name>");
203                            sb.append(servletName);
204                            sb.append("</servlet-name>");
205                            sb.append("<url-pattern>/");
206                            sb.append(portletName);
207                            sb.append("/*</url-pattern>");
208                            sb.append("</servlet-mapping>");
209                    }
210    
211                    return sb.toString();
212            }
213    
214            public void setupAlloy(File srcFile, File portletXML) throws Exception {
215                    Document document = UnsecureSAXReaderUtil.read(portletXML);
216    
217                    Element rootElement = document.getRootElement();
218    
219                    List<Element> portletElements = rootElement.elements("portlet");
220    
221                    for (Element portletElement : portletElements) {
222                            String portletClassName = portletElement.elementText(
223                                    "portlet-class");
224    
225                            if (!portletClassName.contains(
226                                            AlloyPortlet.class.getSimpleName())) {
227    
228                                    continue;
229                            }
230    
231                            String[] dirNames = FileUtil.listDirs(srcFile + "/WEB-INF/jsp");
232    
233                            for (String dirName : dirNames) {
234                                    File dir = new File(
235                                            srcFile + "/WEB-INF/jsp/" + dirName + "/views");
236    
237                                    if (!dir.exists() || !dir.isDirectory()) {
238                                            continue;
239                                    }
240    
241                                    copyDependencyXml("touch.jsp", dir.toString());
242                            }
243    
244                            break;
245                    }
246            }
247    
248            @Override
249            public void updateDeployDirectory(File srcFile) throws Exception {
250                    boolean customPortletXML = false;
251    
252                    try {
253                            customPortletXML = PrefsPropsUtil.getBoolean(
254                                    PropsKeys.AUTO_DEPLOY_CUSTOM_PORTLET_XML,
255                                    PropsValues.AUTO_DEPLOY_CUSTOM_PORTLET_XML);
256                    }
257                    catch (Exception e) {
258    
259                            // This will only happen when running the deploy tool in Ant in the
260                            // classical way where the WAR file is actually massaged and
261                            // packaged.
262    
263                            customPortletXML = PropsValues.AUTO_DEPLOY_CUSTOM_PORTLET_XML;
264                    }
265    
266                    customPortletXML = GetterUtil.getBoolean(
267                            System.getProperty("deployer.custom.portlet.xml"),
268                            customPortletXML);
269    
270                    if (!customPortletXML) {
271                            return;
272                    }
273    
274                    File portletXML = new File(
275                            srcFile + "/WEB-INF/" + Portal.PORTLET_XML_FILE_NAME_STANDARD);
276    
277                    if (portletXML.exists()) {
278                            File portletCustomXML = new File(
279                                    srcFile + "/WEB-INF/" + Portal.PORTLET_XML_FILE_NAME_CUSTOM);
280    
281                            if (portletCustomXML.exists()) {
282                                    portletCustomXML.delete();
283                            }
284    
285                            portletXML.renameTo(portletCustomXML);
286                    }
287            }
288    
289            public void updatePortletXML(File portletXML) throws Exception {
290                    if (!portletXML.exists()) {
291                            return;
292                    }
293    
294                    String content = FileUtil.read(portletXML);
295    
296                    content = StringUtil.replace(
297                            content, "com.liferay.util.bridges.jsp.JSPPortlet",
298                            MVCPortlet.class.getName());
299    
300                    FileUtil.write(portletXML, content);
301            }
302    
303    }