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