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