1   /**
2    * Copyright (c) 2000-2007 Liferay, Inc. All rights reserved.
3    *
4    * Permission is hereby granted, free of charge, to any person obtaining a copy
5    * of this software and associated documentation files (the "Software"), to deal
6    * in the Software without restriction, including without limitation the rights
7    * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
8    * copies of the Software, and to permit persons to whom the Software is
9    * furnished to do so, subject to the following conditions:
10   *
11   * The above copyright notice and this permission notice shall be included in
12   * all copies or substantial portions of the Software.
13   *
14   * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15   * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16   * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
17   * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
18   * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
19   * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
20   * SOFTWARE.
21   */
22  
23  package com.liferay.portal.tools;
24  
25  import com.liferay.portal.kernel.plugin.PluginPackage;
26  import com.liferay.portal.kernel.util.GetterUtil;
27  import com.liferay.portal.kernel.util.StringMaker;
28  import com.liferay.portal.kernel.util.Validator;
29  import com.liferay.portal.util.PortalUtil;
30  import com.liferay.portal.util.PrefsPropsUtil;
31  import com.liferay.portal.util.PropsUtil;
32  import com.liferay.util.FileUtil;
33  import com.liferay.util.TextFormatter;
34  import com.liferay.util.xml.XMLFormatter;
35  import com.liferay.util.xml.XMLMerger;
36  import com.liferay.util.xml.descriptor.FacesXMLDescriptor;
37  
38  import java.io.File;
39  
40  import java.util.ArrayList;
41  import java.util.HashMap;
42  import java.util.Iterator;
43  import java.util.List;
44  import java.util.Map;
45  import java.util.Properties;
46  
47  import org.dom4j.Document;
48  import org.dom4j.Element;
49  
50  /**
51   * <a href="PortletDeployer.java.html"><b><i>View Source</i></b></a>
52   *
53   * @author Brian Wing Shun Chan
54   * @author Brian Myunghun Kim
55   *
56   */
57  public class PortletDeployer extends BaseDeployer {
58  
59      public static final String JSF_MYFACES =
60          "org.apache.myfaces.portlet.MyFacesGenericPortlet";
61  
62      public static final String JSF_SUN =
63          "com.sun.faces.portlet.FacesPortlet";
64  
65      public static final String LIFERAY_RENDER_KIT_FACTORY =
66          "com.liferay.util.jsf.sun.faces.renderkit.LiferayRenderKitFactoryImpl";
67  
68      public static final String MYFACES_CONTEXT_FACTORY =
69          "com.liferay.util.bridges.jsf.myfaces.MyFacesContextFactoryImpl";
70  
71      public static void main(String[] args) {
72          List wars = new ArrayList();
73          List jars = new ArrayList();
74  
75          for (int i = 0; i < args.length; i++) {
76              if (args[i].endsWith(".war")) {
77                  wars.add(args[i]);
78              }
79              else if (args[i].endsWith(".jar")) {
80                  jars.add(args[i]);
81              }
82          }
83  
84          new PortletDeployer(wars, jars);
85      }
86  
87      protected PortletDeployer() {
88      }
89  
90      protected PortletDeployer(List wars, List jars) {
91          super(wars, jars);
92      }
93  
94      protected void checkArguments() {
95          super.checkArguments();
96  
97          if (Validator.isNull(portletTaglibDTD)) {
98              throw new IllegalArgumentException(
99                  "The system property deployer.portlet.taglib.dtd is not set");
100         }
101     }
102 
103     protected String getExtraContent(
104             double webXmlVersion, File srcFile, String displayName)
105         throws Exception {
106 
107         String extraContent = super.getExtraContent(
108             webXmlVersion, srcFile, displayName);
109 
110         extraContent +=
111             "<listener>" +
112             "<listener-class>" +
113             "com.liferay.portal.kernel.servlet.PortletContextListener" +
114             "</listener-class>" +
115             "</listener>";
116 
117         File facesXML = new File(srcFile + "/WEB-INF/faces-config.xml");
118         File portletXML = new File(
119             srcFile + "/WEB-INF/" + PortalUtil.PORTLET_XML_FILE_NAME_STANDARD);
120         File webXML = new File(srcFile + "/WEB-INF/web.xml");
121 
122         extraContent += getServletContent(portletXML, webXML);
123 
124         setupJSF(facesXML, portletXML);
125 
126         if (_sunFacesPortlet) {
127             extraContent +=
128                 "<listener>" +
129                 "<listener-class>" +
130                 "com.liferay.util.bridges.jsf.sun.LiferayConfigureListener" +
131                 "</listener-class>" +
132                 "</listener>";
133         }
134 
135         return extraContent;
136     }
137 
138     protected String getServletContent(File portletXML, File webXML)
139         throws Exception {
140 
141         StringMaker sm = new StringMaker();
142 
143         // Add wrappers for portlets
144 
145         Document doc = PortalUtil.readDocumentFromFile(portletXML);
146 
147         Element root = doc.getRootElement();
148 
149         Iterator itr1 = root.elements("portlet").iterator();
150 
151         while (itr1.hasNext()) {
152             Element portlet = (Element)itr1.next();
153 
154             String portletName = PortalUtil.getJsSafePortletId(
155                 portlet.elementText("portlet-name"));
156             String portletClass = portlet.elementText("portlet-class");
157 
158             sm.append("<servlet>");
159             sm.append("<servlet-name>");
160             sm.append(portletName);
161             sm.append("</servlet-name>");
162             sm.append("<servlet-class>");
163             sm.append("com.liferay.portal.kernel.servlet.PortletServlet");
164             sm.append("</servlet-class>");
165             sm.append("<init-param>");
166             sm.append("<param-name>portlet-class</param-name>");
167             sm.append("<param-value>");
168             sm.append(portletClass);
169             sm.append("</param-value>");
170             sm.append("</init-param>");
171             sm.append("<load-on-startup>0</load-on-startup>");
172             sm.append("</servlet>");
173 
174             sm.append("<servlet-mapping>");
175             sm.append("<servlet-name>");
176             sm.append(portletName);
177             sm.append("</servlet-name>");
178             sm.append("<url-pattern>/");
179             sm.append(portletName);
180             sm.append("/*</url-pattern>");
181             sm.append("</servlet-mapping>");
182         }
183 
184         // Make sure there is a company id specified
185 
186         doc = PortalUtil.readDocumentFromFile(webXML);
187 
188         root = doc.getRootElement();
189 
190         // Remove deprecated references to SharedServletWrapper
191 
192         itr1 = root.elements("servlet").iterator();
193 
194         while (itr1.hasNext()) {
195             Element servlet = (Element)itr1.next();
196 
197             String icon = servlet.elementText("icon");
198             String servletName = servlet.elementText("servlet-name");
199             String displayName = servlet.elementText("display-name");
200             String description = servlet.elementText("description");
201             String servletClass = servlet.elementText("servlet-class");
202             List initParams = servlet.elements("init-param");
203             String loadOnStartup = servlet.elementText("load-on-startup");
204             String runAs = servlet.elementText("run-as");
205             List securityRoleRefs = servlet.elements("security-role-ref");
206 
207             if ((servletClass != null) &&
208                 (servletClass.equals(
209                     "com.liferay.portal.servlet.SharedServletWrapper"))) {
210 
211                 sm.append("<servlet>");
212 
213                 if (icon != null) {
214                     sm.append("<icon>");
215                     sm.append(icon);
216                     sm.append("</icon>");
217                 }
218 
219                 if (servletName != null) {
220                     sm.append("<servlet-name>");
221                     sm.append(servletName);
222                     sm.append("</servlet-name>");
223                 }
224 
225                 if (displayName != null) {
226                     sm.append("<display-name>");
227                     sm.append(displayName);
228                     sm.append("</display-name>");
229                 }
230 
231                 if (description != null) {
232                     sm.append("<description>");
233                     sm.append(description);
234                     sm.append("</description>");
235                 }
236 
237                 Iterator itr2 = initParams.iterator();
238 
239                 while (itr2.hasNext()) {
240                     Element initParam = (Element)itr2.next();
241 
242                     String paramName = initParam.elementText("param-name");
243                     String paramValue = initParam.elementText("param-value");
244 
245                     if ((paramName != null) &&
246                         (paramName.equals("servlet-class"))) {
247 
248                         sm.append("<servlet-class>");
249                         sm.append(paramValue);
250                         sm.append("</servlet-class>");
251                     }
252                 }
253 
254                 itr2 = initParams.iterator();
255 
256                 while (itr2.hasNext()) {
257                     Element initParam = (Element)itr2.next();
258 
259                     String paramName = initParam.elementText("param-name");
260                     String paramValue = initParam.elementText("param-value");
261                     String paramDesc = initParam.elementText("description");
262 
263                     if ((paramName != null) &&
264                         (!paramName.equals("servlet-class"))) {
265 
266                         sm.append("<init-param>");
267                         sm.append("<param-name>");
268                         sm.append(paramName);
269                         sm.append("</param-name>");
270 
271                         if (paramValue != null) {
272                             sm.append("<param-value>");
273                             sm.append(paramValue);
274                             sm.append("</param-value>");
275                         }
276 
277                         if (paramDesc != null) {
278                             sm.append("<description>");
279                             sm.append(paramDesc);
280                             sm.append("</description>");
281                         }
282 
283                         sm.append("</init-param>");
284                     }
285                 }
286 
287                 if (loadOnStartup != null) {
288                     sm.append("<load-on-startup>");
289                     sm.append(loadOnStartup);
290                     sm.append("</load-on-startup>");
291                 }
292 
293                 if (runAs != null) {
294                     sm.append("<run-as>");
295                     sm.append(runAs);
296                     sm.append("</run-as>");
297                 }
298 
299                 itr2 = securityRoleRefs.iterator();
300 
301                 while (itr2.hasNext()) {
302                     Element roleRef = (Element)itr2.next();
303 
304                     String roleDesc = roleRef.elementText("description");
305                     String roleName = roleRef.elementText("role-name");
306                     String roleLink = roleRef.elementText("role-link");
307 
308                     sm.append("<security-role-ref>");
309 
310                     if (roleDesc != null) {
311                         sm.append("<description>");
312                         sm.append(roleDesc);
313                         sm.append("</description>");
314                     }
315 
316                     if (roleName != null) {
317                         sm.append("<role-name>");
318                         sm.append(roleName);
319                         sm.append("</role-name>");
320                     }
321 
322                     if (roleLink != null) {
323                         sm.append("<role-link>");
324                         sm.append(roleLink);
325                         sm.append("</role-link>");
326                     }
327 
328                     sm.append("</security-role-ref>");
329                 }
330 
331                 sm.append("</servlet>");
332             }
333         }
334 
335         return sm.toString();
336     }
337 
338     protected void processPluginPackageProperties(
339             File srcFile, String displayName, PluginPackage pluginPackage)
340         throws Exception {
341 
342         if (pluginPackage == null) {
343             return;
344         }
345 
346         Properties props = getPluginPackageProperties(srcFile);
347 
348         if ((props == null) || (props.size() == 0)) {
349             return;
350         }
351 
352         String moduleGroupId = pluginPackage.getGroupId();
353         String moduleArtifactId = pluginPackage.getArtifactId();
354         String moduleVersion = pluginPackage.getVersion();
355 
356         String pluginName = pluginPackage.getName();
357         String pluginType = (String)pluginPackage.getTypes().get(0);
358         String pluginTypeName = TextFormatter.format(
359             pluginType, TextFormatter.J);
360 
361         if (!pluginType.equals("portlet")) {
362             return;
363         }
364 
365         String tags = getPluginPackageTagsXml(pluginPackage.getTags());
366         String shortDescription = pluginPackage.getShortDescription();
367         String longDescription = pluginPackage.getLongDescription();
368         String changeLog = pluginPackage.getChangeLog();
369         String pageURL = pluginPackage.getPageURL();
370         String author = pluginPackage.getAuthor();
371         String licenses = getPluginPackageLicensesXml(
372             pluginPackage.getLicenses());
373         String liferayVersions = getPluginPackageLiferayVersionsXml(
374             pluginPackage.getLiferayVersions());
375 
376         Map filterMap = new HashMap();
377 
378         filterMap.put("module_group_id", moduleGroupId);
379         filterMap.put("module_artifact_id", moduleArtifactId);
380         filterMap.put("module_version", moduleVersion);
381 
382         filterMap.put("plugin_name", pluginName);
383         filterMap.put("plugin_type", pluginType);
384         filterMap.put("plugin_type_name", pluginTypeName);
385 
386         filterMap.put("tags", tags);
387         filterMap.put("short_description", shortDescription);
388         filterMap.put("long_description", longDescription);
389         filterMap.put("change_log", changeLog);
390         filterMap.put("page_url", pageURL);
391         filterMap.put("author", author);
392         filterMap.put("licenses", licenses);
393         filterMap.put("liferay_versions", liferayVersions);
394 
395         copyDependencyXml(
396             "liferay-plugin-package.xml", srcFile + "/WEB-INF", filterMap,
397             true);
398     }
399 
400     protected void setupJSF(File facesXML, File portletXML) throws Exception {
401         _myFacesPortlet = false;
402         _sunFacesPortlet = false;
403 
404         if (!facesXML.exists()) {
405             return;
406         }
407 
408         // portlet.xml
409 
410         Document doc = PortalUtil.readDocumentFromFile(portletXML, true);
411 
412         Element root = doc.getRootElement();
413 
414         List elements = root.elements("portlet");
415 
416         Iterator itr = elements.iterator();
417 
418         while (itr.hasNext()) {
419             Element portlet = (Element)itr.next();
420 
421             String portletClass = portlet.elementText("portlet-class");
422 
423             if (portletClass.equals(JSF_MYFACES)) {
424                 _myFacesPortlet = true;
425 
426                 break;
427             }
428             else if (portletClass.equals(JSF_SUN)) {
429                 _sunFacesPortlet = true;
430 
431                 break;
432             }
433         }
434 
435         // faces-config.xml
436 
437         doc = PortalUtil.readDocumentFromFile(facesXML, true);
438 
439         root = doc.getRootElement();
440 
441         Element factoryEl = root.element("factory");
442 
443         Element renderKitFactoryEl = null;
444         Element facesContextFactoryEl = null;
445 
446         if (factoryEl == null) {
447             factoryEl = root.addElement("factory");
448         }
449 
450         renderKitFactoryEl = factoryEl.element("render-kit-factory");
451         facesContextFactoryEl = factoryEl.element("faces-context-factory");
452 
453         if ((appServerType.equals("orion") && (_sunFacesPortlet) &&
454             (renderKitFactoryEl == null))) {
455 
456             renderKitFactoryEl = factoryEl.addElement("render-kit-factory");
457 
458             renderKitFactoryEl.addText(LIFERAY_RENDER_KIT_FACTORY);
459         }
460         else if (_myFacesPortlet && (facesContextFactoryEl == null)) {
461             facesContextFactoryEl =
462                 factoryEl.addElement("faces-context-factory");
463 
464             facesContextFactoryEl.addText(MYFACES_CONTEXT_FACTORY);
465         }
466 
467         if (!appServerType.equals("orion") && (_sunFacesPortlet)) {
468             factoryEl.detach();
469         }
470 
471         XMLMerger merger = new XMLMerger(new FacesXMLDescriptor());
472 
473         merger.organizeXML(doc);
474 
475         FileUtil.write(facesXML, XMLFormatter.toString(doc), true);
476     }
477 
478     protected void updateDeployDirectory(File srcFile) throws Exception {
479         try {
480             if (!PrefsPropsUtil.getBoolean(
481                     PropsUtil.AUTO_DEPLOY_CUSTOM_PORTLET_XML)) {
482 
483                 return;
484             }
485         }
486         catch (Exception e) {
487 
488             // This will only happen when running the deploy tool in Ant in the
489             // classical way where the WAR file is actually massaged and
490             // packaged.
491 
492             if (!GetterUtil.getBoolean(PropsUtil.get(
493                     PropsUtil.AUTO_DEPLOY_CUSTOM_PORTLET_XML))) {
494 
495                 return;
496             }
497         }
498 
499         File portletXML = new File(
500             srcFile + "/WEB-INF/" + PortalUtil.PORTLET_XML_FILE_NAME_STANDARD);
501 
502         if (portletXML.exists()) {
503             File portletCustomXML = new File(
504                 srcFile + "/WEB-INF/" +
505                     PortalUtil.PORTLET_XML_FILE_NAME_CUSTOM);
506 
507             if (portletCustomXML.exists()) {
508                 portletCustomXML.delete();
509             }
510 
511             portletXML.renameTo(portletCustomXML);
512         }
513     }
514 
515     private boolean _myFacesPortlet;
516     private boolean _sunFacesPortlet;
517 
518 }