001    /**
002     * Copyright (c) 2000-2011 Liferay, Inc. All rights reserved.
003     *
004     * The contents of this file are subject to the terms of the Liferay Enterprise
005     * Subscription License ("License"). You may not use this file except in
006     * compliance with the License. You can obtain a copy of the License by
007     * contacting Liferay, Inc. See the License for the specific language governing
008     * permissions and limitations under the License, including but not limited to
009     * distribution rights of the Software.
010     *
011     *
012     *
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.SAXReaderUtil;
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.portal.xml.DocumentImpl;
035    import com.liferay.util.bridges.mvc.MVCPortlet;
036    import com.liferay.util.xml.XMLMerger;
037    import com.liferay.util.xml.descriptor.FacesXMLDescriptor;
038    
039    import java.io.File;
040    
041    import java.util.ArrayList;
042    import java.util.Iterator;
043    import java.util.List;
044    
045    /**
046     * @author Brian Wing Shun Chan
047     * @author Brian Myunghun Kim
048     */
049    public class PortletDeployer extends BaseDeployer {
050    
051            public static final String JSF_MYFACES =
052                    "org.apache.myfaces.portlet.MyFacesGenericPortlet";
053    
054            public static final String JSF_STANDARD =
055                    "javax.portlet.faces.GenericFacesPortlet";
056    
057            public static final String JSF_SUN =
058                    "com.sun.faces.portlet.FacesPortlet";
059    
060            public static final String LIFERAY_RENDER_KIT_FACTORY =
061                    "com.liferay.util.jsf.sun.faces.renderkit.LiferayRenderKitFactoryImpl";
062    
063            public static final String MYFACES_CONTEXT_FACTORY =
064                    "com.liferay.util.bridges.jsf.myfaces.MyFacesContextFactoryImpl";
065    
066            public static void main(String[] args) {
067                    InitUtil.initWithSpring();
068    
069                    List<String> wars = new ArrayList<String>();
070                    List<String> jars = new ArrayList<String>();
071    
072                    for (String arg : args) {
073                            if (arg.endsWith(".war")) {
074                                    wars.add(arg);
075                            }
076                            else if (arg.endsWith(".jar")) {
077                                    jars.add(arg);
078                            }
079                    }
080    
081                    new PortletDeployer(wars, jars);
082            }
083    
084            public PortletDeployer() {
085            }
086    
087            public PortletDeployer(List<String> wars, List<String> jars) {
088                    super(wars, jars);
089            }
090    
091            @Override
092            public void checkArguments() {
093                    super.checkArguments();
094    
095                    if (Validator.isNull(portletTaglibDTD)) {
096                            throw new IllegalArgumentException(
097                                    "The system property deployer.portlet.taglib.dtd is not set");
098                    }
099            }
100    
101            @Override
102            public void copyXmls(
103                            File srcFile, String displayName, PluginPackage pluginPackage)
104                    throws Exception {
105    
106                    super.copyXmls(srcFile, displayName, pluginPackage);
107    
108                    if (appServerType.equals(ServerDetector.TOMCAT_ID)) {
109                            copyDependencyXml("context.xml", srcFile + "/META-INF");
110                    }
111    
112                    copyDependencyXml(
113                            "_servlet_context_include.jsp", srcFile + "/WEB-INF/jsp");
114            }
115    
116            @Override
117            public String getExtraContent(
118                            double webXmlVersion, File srcFile, String displayName)
119                    throws Exception {
120    
121                    StringBundler sb = new StringBundler();
122    
123                    String extraContent = super.getExtraContent(
124                            webXmlVersion, srcFile, displayName);
125    
126                    sb.append(extraContent);
127    
128                    if (ServerDetector.isWebSphere()) {
129                            sb.append("<context-param>");
130                            sb.append("<param-name>");
131                            sb.append("com.ibm.websphere.portletcontainer.");
132                            sb.append("PortletDeploymentEnabled");
133                            sb.append("</param-name>");
134                            sb.append("<param-value>false</param-value>");
135                            sb.append("</context-param>");
136                    }
137    
138                    File facesXML = new File(srcFile + "/WEB-INF/faces-config.xml");
139                    File portletXML = new File(
140                            srcFile + "/WEB-INF/" + Portal.PORTLET_XML_FILE_NAME_STANDARD);
141                    File webXML = new File(srcFile + "/WEB-INF/web.xml");
142    
143                    updatePortletXML(portletXML);
144    
145                    sb.append(getServletContent(portletXML, webXML));
146    
147                    setupJSF(facesXML, portletXML);
148    
149                    if (_sunFacesPortlet) {
150    
151                            // LiferayConfigureListener
152    
153                            sb.append("<listener>");
154                            sb.append("<listener-class>");
155                            sb.append("com.liferay.util.bridges.jsf.sun.");
156                            sb.append("LiferayConfigureListener");
157                            sb.append("</listener-class>");
158                            sb.append("</listener>");
159                    }
160    
161                    // PortletContextListener
162    
163                    sb.append("<listener>");
164                    sb.append("<listener-class>");
165                    sb.append("com.liferay.portal.kernel.servlet.PortletContextListener");
166                    sb.append("</listener-class>");
167                    sb.append("</listener>");
168    
169                    // Ignore filters
170    
171                    sb.append(getIgnoreFiltersContent(srcFile));
172    
173                    // Speed filters
174    
175                    sb.append(getSpeedFiltersContent(srcFile));
176    
177                    // Servlet context include filters
178    
179                    sb.append(
180                            getServletContextIncludeFiltersContent(webXmlVersion, srcFile));
181    
182                    return sb.toString();
183            }
184    
185            @Override
186            public String getPluginType() {
187                    return Plugin.TYPE_PORTLET;
188            }
189    
190            public String getServletContent(File portletXML, File webXML)
191                    throws Exception {
192    
193                    StringBundler sb = new StringBundler();
194    
195                    // Add wrappers for portlets
196    
197                    Document doc = SAXReaderUtil.read(portletXML);
198    
199                    Element root = doc.getRootElement();
200    
201                    Iterator<Element> itr1 = root.elements("portlet").iterator();
202    
203                    while (itr1.hasNext()) {
204                            Element portlet = itr1.next();
205    
206                            String portletName = PortalUtil.getJsSafePortletId(
207                                    portlet.elementText("portlet-name"));
208                            String portletClass = portlet.elementText("portlet-class");
209    
210                            String servletName = portletName + " Servlet";
211    
212                            sb.append("<servlet>");
213                            sb.append("<servlet-name>");
214                            sb.append(servletName);
215                            sb.append("</servlet-name>");
216                            sb.append("<servlet-class>");
217                            sb.append("com.liferay.portal.kernel.servlet.PortletServlet");
218                            sb.append("</servlet-class>");
219                            sb.append("<init-param>");
220                            sb.append("<param-name>portlet-class</param-name>");
221                            sb.append("<param-value>");
222                            sb.append(portletClass);
223                            sb.append("</param-value>");
224                            sb.append("</init-param>");
225                            sb.append("<load-on-startup>0</load-on-startup>");
226                            sb.append("</servlet>");
227    
228                            sb.append("<servlet-mapping>");
229                            sb.append("<servlet-name>");
230                            sb.append(servletName);
231                            sb.append("</servlet-name>");
232                            sb.append("<url-pattern>/");
233                            sb.append(portletName);
234                            sb.append("/*</url-pattern>");
235                            sb.append("</servlet-mapping>");
236                    }
237    
238                    // Make sure there is a company id specified
239    
240                    doc = SAXReaderUtil.read(webXML);
241    
242                    root = doc.getRootElement();
243    
244                    // Remove deprecated references to SharedServletWrapper
245    
246                    itr1 = root.elements("servlet").iterator();
247    
248                    while (itr1.hasNext()) {
249                            Element servlet = itr1.next();
250    
251                            String icon = servlet.elementText("icon");
252                            String servletName = servlet.elementText("servlet-name");
253                            String displayName = servlet.elementText("display-name");
254                            String description = servlet.elementText("description");
255                            String servletClass = servlet.elementText("servlet-class");
256                            List<Element> initParams = servlet.elements("init-param");
257                            String loadOnStartup = servlet.elementText("load-on-startup");
258                            String runAs = servlet.elementText("run-as");
259                            List<Element> securityRoleRefs = servlet.elements(
260                                    "security-role-ref");
261    
262                            if ((servletClass != null) &&
263                                    (servletClass.equals(
264                                            "com.liferay.portal.servlet.SharedServletWrapper"))) {
265    
266                                    sb.append("<servlet>");
267    
268                                    if (icon != null) {
269                                            sb.append("<icon>");
270                                            sb.append(icon);
271                                            sb.append("</icon>");
272                                    }
273    
274                                    if (servletName != null) {
275                                            sb.append("<servlet-name>");
276                                            sb.append(servletName);
277                                            sb.append("</servlet-name>");
278                                    }
279    
280                                    if (displayName != null) {
281                                            sb.append("<display-name>");
282                                            sb.append(displayName);
283                                            sb.append("</display-name>");
284                                    }
285    
286                                    if (description != null) {
287                                            sb.append("<description>");
288                                            sb.append(description);
289                                            sb.append("</description>");
290                                    }
291    
292                                    Iterator<Element> itr2 = initParams.iterator();
293    
294                                    while (itr2.hasNext()) {
295                                            Element initParam = itr2.next();
296    
297                                            String paramName = initParam.elementText("param-name");
298                                            String paramValue = initParam.elementText("param-value");
299    
300                                            if ((paramName != null) &&
301                                                    (paramName.equals("servlet-class"))) {
302    
303                                                    sb.append("<servlet-class>");
304                                                    sb.append(paramValue);
305                                                    sb.append("</servlet-class>");
306                                            }
307                                    }
308    
309                                    itr2 = initParams.iterator();
310    
311                                    while (itr2.hasNext()) {
312                                            Element initParam = itr2.next();
313    
314                                            String paramName = initParam.elementText("param-name");
315                                            String paramValue = initParam.elementText("param-value");
316                                            String paramDesc = initParam.elementText("description");
317    
318                                            if ((paramName != null) &&
319                                                    (!paramName.equals("servlet-class"))) {
320    
321                                                    sb.append("<init-param>");
322                                                    sb.append("<param-name>");
323                                                    sb.append(paramName);
324                                                    sb.append("</param-name>");
325    
326                                                    if (paramValue != null) {
327                                                            sb.append("<param-value>");
328                                                            sb.append(paramValue);
329                                                            sb.append("</param-value>");
330                                                    }
331    
332                                                    if (paramDesc != null) {
333                                                            sb.append("<description>");
334                                                            sb.append(paramDesc);
335                                                            sb.append("</description>");
336                                                    }
337    
338                                                    sb.append("</init-param>");
339                                            }
340                                    }
341    
342                                    if (loadOnStartup != null) {
343                                            sb.append("<load-on-startup>");
344                                            sb.append(loadOnStartup);
345                                            sb.append("</load-on-startup>");
346                                    }
347    
348                                    if (runAs != null) {
349                                            sb.append("<run-as>");
350                                            sb.append(runAs);
351                                            sb.append("</run-as>");
352                                    }
353    
354                                    itr2 = securityRoleRefs.iterator();
355    
356                                    while (itr2.hasNext()) {
357                                            Element roleRef = itr2.next();
358    
359                                            String roleDesc = roleRef.elementText("description");
360                                            String roleName = roleRef.elementText("role-name");
361                                            String roleLink = roleRef.elementText("role-link");
362    
363                                            sb.append("<security-role-ref>");
364    
365                                            if (roleDesc != null) {
366                                                    sb.append("<description>");
367                                                    sb.append(roleDesc);
368                                                    sb.append("</description>");
369                                            }
370    
371                                            if (roleName != null) {
372                                                    sb.append("<role-name>");
373                                                    sb.append(roleName);
374                                                    sb.append("</role-name>");
375                                            }
376    
377                                            if (roleLink != null) {
378                                                    sb.append("<role-link>");
379                                                    sb.append(roleLink);
380                                                    sb.append("</role-link>");
381                                            }
382    
383                                            sb.append("</security-role-ref>");
384                                    }
385    
386                                    sb.append("</servlet>");
387                            }
388                    }
389    
390                    return sb.toString();
391            }
392    
393            public void setupJSF(File facesXML, File portletXML) throws Exception {
394                    _myFacesPortlet = false;
395                    _sunFacesPortlet = false;
396    
397                    if (!facesXML.exists()) {
398                            return;
399                    }
400    
401                    // portlet.xml
402    
403                    Document doc = SAXReaderUtil.read(portletXML, true);
404    
405                    Element root = doc.getRootElement();
406    
407                    List<Element> elements = root.elements("portlet");
408    
409                    Iterator<Element> itr = elements.iterator();
410    
411                    while (itr.hasNext()) {
412                            Element portlet = itr.next();
413    
414                            String portletClass = portlet.elementText("portlet-class");
415    
416                            if (portletClass.equals(JSF_MYFACES)) {
417                                    _myFacesPortlet = true;
418    
419                                    break;
420                            }
421                            else if (portletClass.equals(JSF_SUN)) {
422                                    _sunFacesPortlet = true;
423    
424                                    break;
425                            }
426                    }
427    
428                    // faces-config.xml
429    
430                    doc = SAXReaderUtil.read(facesXML, true);
431    
432                    root = doc.getRootElement();
433    
434                    Element factoryEl = root.element("factory");
435    
436                    Element renderKitFactoryEl = null;
437                    Element facesContextFactoryEl = null;
438    
439                    if (factoryEl == null) {
440                            factoryEl = root.addElement("factory");
441                    }
442    
443                    renderKitFactoryEl = factoryEl.element("render-kit-factory");
444                    facesContextFactoryEl = factoryEl.element("faces-context-factory");
445    
446                    if ((appServerType.equals("orion") && (_sunFacesPortlet) &&
447                            (renderKitFactoryEl == null))) {
448    
449                            renderKitFactoryEl = factoryEl.addElement("render-kit-factory");
450    
451                            renderKitFactoryEl.addText(LIFERAY_RENDER_KIT_FACTORY);
452                    }
453                    else if (_myFacesPortlet && (facesContextFactoryEl == null)) {
454                            facesContextFactoryEl = factoryEl.addElement(
455                                    "faces-context-factory");
456    
457                            facesContextFactoryEl.addText(MYFACES_CONTEXT_FACTORY);
458                    }
459    
460                    if (!appServerType.equals("orion") && (_sunFacesPortlet)) {
461                            factoryEl.detach();
462                    }
463    
464                    XMLMerger merger = new XMLMerger(new FacesXMLDescriptor());
465    
466                    DocumentImpl docImpl = (DocumentImpl)doc;
467    
468                    merger.organizeXML(docImpl.getWrappedDocument());
469    
470                    FileUtil.write(facesXML, doc.formattedString(), true);
471            }
472    
473            @Override
474            public void updateDeployDirectory(File srcFile) throws Exception {
475                    boolean customPortletXML = false;
476    
477                    try {
478                            customPortletXML = PrefsPropsUtil.getBoolean(
479                                    PropsKeys.AUTO_DEPLOY_CUSTOM_PORTLET_XML,
480                                    PropsValues.AUTO_DEPLOY_CUSTOM_PORTLET_XML);
481                    }
482                    catch (Exception e) {
483    
484                            // This will only happen when running the deploy tool in Ant in the
485                            // classical way where the WAR file is actually massaged and
486                            // packaged.
487    
488                            customPortletXML = PropsValues.AUTO_DEPLOY_CUSTOM_PORTLET_XML;
489                    }
490    
491                    customPortletXML = GetterUtil.getBoolean(
492                            System.getProperty("deployer.custom.portlet.xml"),
493                            customPortletXML);
494    
495                    if (!customPortletXML) {
496                            return;
497                    }
498    
499                    File portletXML = new File(
500                            srcFile + "/WEB-INF/" + Portal.PORTLET_XML_FILE_NAME_STANDARD);
501    
502                    if (portletXML.exists()) {
503                            File portletCustomXML = new File(
504                                    srcFile + "/WEB-INF/" + Portal.PORTLET_XML_FILE_NAME_CUSTOM);
505    
506                            if (portletCustomXML.exists()) {
507                                    portletCustomXML.delete();
508                            }
509    
510                            portletXML.renameTo(portletCustomXML);
511                    }
512            }
513    
514            public void updatePortletXML(File portletXML) throws Exception {
515                    if (!portletXML.exists()) {
516                            return;
517                    }
518    
519                    String content = FileUtil.read(portletXML);
520    
521                    content = StringUtil.replace(
522                            content, "com.liferay.util.bridges.jsp.JSPPortlet",
523                            MVCPortlet.class.getName());
524    
525                    FileUtil.write(portletXML, content);
526            }
527    
528            private boolean _myFacesPortlet;
529            private boolean _sunFacesPortlet;
530    
531    }