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