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