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