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