001: /*
002: * Copyright 2003 Sun Microsystems, Inc. All rights reserved.
003: * PROPRIETARY/CONFIDENTIAL. Use of this product is subject to license terms.
004: */
005:
006: package com.sun.portal.portlet.cli;
007:
008: import java.util.List;
009: import java.util.ArrayList;
010: import java.util.Properties;
011: import java.util.Iterator;
012:
013: import java.io.File;
014: import java.io.FileInputStream;
015: import java.io.FileOutputStream;
016: import java.io.InputStream;
017: import java.io.IOException;
018: import java.io.FileNotFoundException;
019:
020: import java.io.InputStream;
021: import java.io.IOException;
022: import java.io.File;
023:
024: import org.jdom.Document;
025: import org.jdom.Element;
026: import org.jdom.Comment;
027: import org.jdom.JDOMException;
028: import org.jdom.IllegalAddException;
029: import org.jdom.input.SAXBuilder;
030: import org.jdom.output.XMLOutputter;
031: import org.jdom.output.Format;
032:
033: /**
034: * PDWebAppUpdater is responsible for updating the web.xml file
035: * in the PortletApplication war file.
036: *
037: * The addWebAppParam() method takes the InputStream of the web.xml file
038: * and checks for the listener classes and PAE servlet associated with
039: * the PortletContainer. If any of these elements are found in the Document,
040: * it will remove them and readd them.
041: *
042: * The removeWebAppParam() method takes the InputStream of the web.xml file
043: * and removes the listener classes, context Params, PAE servlet associated
044: * with the portletcontainer.
045: *
046: * The isWebAppUpdated() method checks if any of the elements associated with
047: * the portletContainer are present in the web.xml document and returns true/false
048: * based on the results.
049: *
050: */
051: public class PDWebAppUpdater {
052:
053: private static final List listenerClasses = new ArrayList();
054:
055: private static final String servletClass = "com.sun.portal.portletappengine.PortletAppEngineServlet";
056: private static final String servletName = "PortletAppEngineServlet";
057: private static final String loaderServletClass = "com.sun.portal.portletappengine.LoadServletContextLsnrServlet";
058: private static final String loaderServletName = "LoadServletContextLsnrServlet";
059: private static final String servletMapping = "/servlet/PortletAppEngineServlet";
060: private static final List contextParams = new ArrayList();
061: static {
062:
063: listenerClasses
064: .add("com.sun.portal.portletappengine.impl.LifecycleManagerContextListenerImpl");
065: listenerClasses
066: .add("com.sun.portal.portletappengine.impl.RequestResponseFactoryContextListenerImpl");
067:
068: contextParams.add("request_response_factory.minSizeParam");
069: contextParams.add("request_response_factory.maxSizeParam");
070: contextParams.add("request_response_factory.partitionParam");
071: contextParams.add("DDSchemaLocation");
072:
073: }
074:
075: private static final String CONTEXT_PARAM = "context-param";
076: private static final String PARAM_NAME = "param-name";
077: private static final String PARAM_VALUE = "param-value";
078: private static final String LISTENER = "listener";
079: private static final String LISTENER_CLASS = "listener-class";
080: private static final String SERVLET = "servlet";
081: private static final String SERVLET_NAME = "servlet-name";
082: private static final String SERVLET_CLASS = "servlet-class";
083: private static final String LOAD_ON_STARTUP = "load-on-startup";
084: private static final String SERVLET_MAPPING = "servlet-mapping";
085: private static final String URL_PATTERN = "url-pattern";
086: private static final String SECURITY_ROLE = "security-role";
087: private static final String ROLE_NAME = "role-name";
088: private static final String TAGLIB = "taglib";
089: private static final String TAGLIB_URI = "taglib-uri";
090: private static final String TAGLIB_LOCATION = "taglib-location";
091:
092: private static final String taglibURI = "http://java.sun.com/portlet";
093: private static final String taglibLocation = "/WEB-INF/portlet.tld";
094:
095: private static final String contextParamComment = "Init Parameters";
096: private static final String listenerClassComment = "Listener Classes";
097: private static final String servletComment = "PAE Servlet";
098: private static final String loaderServletComment = "ServletContext Loader Servlet";
099: private static final String servletMappingComment = "PAE Servlet Mapping";
100: private static final String taglibComment = "taglib for portlets";
101: private static final String indent = " ";
102: private static final boolean newLines = true;
103:
104: private static List elementBeforeCtxParam = new ArrayList();
105:
106: private static List elementBeforeListener = new ArrayList();
107: private static List elementBeforeTaglib = new ArrayList();
108: private static List elementBeforeServletMapping = new ArrayList();
109:
110: static {
111: elementBeforeCtxParam.add("icon");
112: elementBeforeCtxParam.add("display-name");
113: elementBeforeCtxParam.add("description");
114: elementBeforeCtxParam.add("distributable");
115: elementBeforeCtxParam.add("context-param");
116:
117: elementBeforeListener.add("filter");
118: elementBeforeListener.add("filter-mapping");
119: elementBeforeListener.add("listener");
120:
121: elementBeforeServletMapping.add("servlet");
122:
123: elementBeforeTaglib.add("servlet-mapping");
124: elementBeforeTaglib.add("session-config");
125: elementBeforeTaglib.add("mime-mapping");
126: elementBeforeTaglib.add("welcome-file-list");
127: elementBeforeTaglib.add("error-page");
128: }
129:
130: private static final String WEB_INF_PREFIX = "WEB-INF"
131: + File.separator;
132: private static final String WEB_XML = "web.xml";
133: private static final String WEB_XML_NAME = WEB_INF_PREFIX + WEB_XML;
134: private static final String PAE_PREFIX = WEB_INF_PREFIX + "lib"
135: + File.separator;
136:
137: public static List getRoles(InputStream in) throws IOException,
138: PortletDeployerException {
139: Document doc = getDocument(in);
140: Element root = doc.getRootElement();
141: List roles = new ArrayList();
142: List sRoleElements = root.getChildren(SECURITY_ROLE);
143: for (int i = 0; i < sRoleElements.size(); i++) {
144: Element sRoleElement = (Element) sRoleElements.get(i);
145: Element roleName = sRoleElement.getChild(ROLE_NAME);
146: if (roleName != null) {
147: String role = roleName.getTextTrim();
148: if (role != null && role.length() != 0) {
149: roles.add(role);
150: }
151: }
152:
153: }
154: return roles;
155: }
156:
157: public static File addWebAppParam(InputStream in,
158: Properties configProps, String portletAppName)
159: throws IOException, PortletDeployerException {
160: Document doc = getDocument(in);
161: Element root = doc.getRootElement();
162:
163: // check if the web.xml is already updated, if it is remove
164: // the updates first and then readd them.
165: boolean updated = isWebAppUpdated(root, configProps);
166: if (updated) {
167: try {
168: removeElements(root, configProps);
169: } catch (IllegalAddException iae) {
170: Object[] tokens = { iae.toString() };
171: throw new PortletDeployerException("errorIllegalAdd",
172: tokens);
173: }
174: }
175:
176: try {
177: addElements(root, portletAppName, configProps);
178: } catch (IllegalAddException iae) {
179: Object[] tokens = { iae.toString() };
180: throw new PortletDeployerException("errorIllegalAdd",
181: tokens);
182: }
183:
184: return createUpdatedFile(doc);
185: }
186:
187: public static File removeWebAppParam(InputStream in,
188: Properties configProps) throws IOException,
189: PortletDeployerException {
190: Document doc = getDocument(in);
191: Element root = doc.getRootElement();
192: try {
193: removeElements(root, configProps);
194: } catch (IllegalAddException iae) {
195: Object[] tokens = { iae.toString() };
196: throw new PortletDeployerException("errorIllegalAdd",
197: tokens);
198: }
199: //System.out.println("creating updated file");
200: return createUpdatedFile(doc);
201: }
202:
203: public static boolean isWebAppUpdated(InputStream in,
204: Properties configProps) throws PortletDeployerException {
205: Document doc = getDocument(in);
206: Element root = doc.getRootElement();
207:
208: return isWebAppUpdated(root, configProps);
209: }
210:
211: private static boolean isWebAppUpdated(Element root,
212: Properties configProps) throws PortletDeployerException {
213: boolean updated = false;
214:
215: List children = root.getChildren();
216: Iterator itr = children.iterator();
217: while (itr.hasNext()) {
218: Element child = (Element) itr.next();
219: if (child.getName().equals(CONTEXT_PARAM)) {
220: String param = child.getChildTextTrim(PARAM_NAME);
221: if (contextParams.contains(param)) {
222: updated = true;
223: return updated;
224: }
225: } else if (child.getName().equals(LISTENER)) {
226: String param = child.getChildTextTrim(LISTENER_CLASS);
227: if (listenerClasses.contains(param)) {
228: updated = true;
229: return updated;
230: }
231: } else if (child.getName().equals(SERVLET)) {
232: String param = child.getChildTextTrim(SERVLET_NAME);
233: if (param.equals(servletName)
234: || param.equals(loaderServletName)) {
235: updated = true;
236: return updated;
237: }
238: }
239: }
240: return updated;
241: }
242:
243: private static Document getDocument(InputStream in)
244: throws PortletDeployerException {
245: // read the web xml document
246: if (in == null) {
247: throw new PortletDeployerException("emptyWebXML");
248: }
249:
250: Document doc = null;
251: try {
252: SAXBuilder builder = new SAXBuilder();
253: builder.setEntityResolver(new NoOpEntityResolver());
254: doc = builder.build(in);
255: } catch (IOException e) {
256: throw new PortletDeployerException("error reading stream "
257: + e.getMessage());
258: } catch (JDOMException je) {
259: Object[] tokens = { je.toString() };
260: throw new PortletDeployerException("errorDocumentBuild",
261: tokens);
262: }
263: return doc;
264: }
265:
266: private static File createUpdatedFile(Document doc)
267: throws IOException {
268:
269: // create a temp file
270: File newWebXMLFile = File.createTempFile("web", ".xml");
271: newWebXMLFile.deleteOnExit();
272:
273: FileOutputStream fos = new FileOutputStream(newWebXMLFile);
274:
275: Format format = Format.getPrettyFormat();
276: format.setIndent(indent);
277: format.setLineSeparator(System.getProperty("line.separator"));
278: format.setEncoding("ISO-8859-1");
279: XMLOutputter fmt = new XMLOutputter(format);
280: fmt.output(doc, fos);
281: //fmt.output(doc, System.out);
282: fos.close();
283:
284: return newWebXMLFile;
285: }
286:
287: private static void addElements(Element root,
288: String portletAppName, Properties configProps)
289: throws IllegalAddException {
290:
291: List children = root.getChildren();
292: int size = children.size();
293:
294: int newSize = size + contextParams.size()
295: + listenerClasses.size() + 1;
296: List newChildren = new ArrayList(newSize);
297:
298: int i = 0;
299: boolean addPortletParam = false;
300: for (i = 0; i < size; i++) {
301: Element child = (Element) children.get(i);
302: if (elementBeforeCtxParam.contains(child.getName())) {
303: newChildren.add(child);
304: } else {
305: newChildren.addAll(genContextParamElements(
306: portletAppName, configProps));
307: addPortletParam = true;
308: break;
309: }
310: }
311: if (!addPortletParam) {
312: newChildren.addAll(genContextParamElements(portletAppName,
313: configProps));
314: addPortletParam = false;
315: }
316: for (i = i; i < size; i++) {
317: Element child = (Element) children.get(i);
318: if (elementBeforeListener.contains(child.getName())) {
319: newChildren.add(child);
320: } else {
321: //newChildren.addAll(genListenerElements());
322: newChildren.addAll(genLoaderServletElements());
323: newChildren.addAll(genServletElements());
324: addPortletParam = true;
325: break;
326: }
327: }
328: if (!addPortletParam) {
329: //newChildren.addAll(genListenerElements());
330: newChildren.addAll(genLoaderServletElements());
331: newChildren.addAll(genServletElements());
332: }
333:
334: boolean addServletMappingParam = false;
335: for (i = i; i < size; i++) {
336: Element child = (Element) children.get(i);
337: if (elementBeforeServletMapping.contains(child.getName())) {
338: newChildren.add(child);
339: } else {
340: newChildren.addAll(genServletMappingElements());
341: addServletMappingParam = true;
342: break;
343: }
344: }
345: if (!addServletMappingParam) {
346: newChildren.addAll(genServletMappingElements());
347: }
348:
349: boolean addTaglibParam = false;
350: for (i = i; i < size; i++) {
351: Element child = (Element) children.get(i);
352: if (elementBeforeTaglib.contains(child.getName())) {
353: newChildren.add(child);
354: } else {
355: newChildren.addAll(genTaglibElements());
356: addTaglibParam = true;
357: break;
358: }
359: }
360: if (!addTaglibParam) {
361: newChildren.addAll(genTaglibElements());
362: }
363: for (i = i; i < size; i++) {
364: newChildren.add(children.get(i));
365: }
366:
367: Iterator it = root.getChildren().iterator();
368: List list = new ArrayList();
369: //need to copy names to avoid simoltanious update of iterator
370: while (it.hasNext())
371: list.add(((Element) it.next()).getName());
372: for (int count = 0; count < list.size(); count++) {
373: //using removeChild and not removeChildren to make sure
374: //next call to the same doesn't fails in case multiple
375: //child has same name
376: root.removeChild((String) list.get(count));
377: }
378: //root.setChildren(newChildren);
379: root.setContent(newChildren);
380: }
381:
382: private static List genContextParamElements(String portletAppName,
383: Properties configProps) {
384:
385: List contextParamElements = new ArrayList(contextParams.size());
386:
387: Comment comment = new Comment(contextParamComment);
388: contextParamElements.add(comment);
389:
390: for (int i = 0; i < contextParams.size(); i++) {
391: Element contextParam = new Element(CONTEXT_PARAM);
392: Element paramName = new Element(PARAM_NAME);
393: paramName.addContent((String) contextParams.get(i));
394: Element paramValue = new Element(PARAM_VALUE);
395: paramValue.addContent(configProps
396: .getProperty((String) contextParams.get(i)));
397: contextParam.addContent(paramName);
398: contextParam.addContent(paramValue);
399: contextParamElements.add(contextParam);
400: }
401:
402: return contextParamElements;
403: }
404:
405: private static List genListenerElements() {
406:
407: List listenerElements = new ArrayList(listenerClasses.size());
408:
409: Comment comment = new Comment(listenerClassComment);
410: listenerElements.add(comment);
411:
412: for (int i = 0; i < listenerClasses.size(); i++) {
413: Element listenerElement = new Element(LISTENER);
414: Element listenerClassElement = new Element(LISTENER_CLASS);
415: listenerClassElement.addContent((String) listenerClasses
416: .get(i));
417: listenerElement.addContent(listenerClassElement);
418: listenerElements.add(listenerElement);
419: }
420:
421: return listenerElements;
422: }
423:
424: private static List genServletElements() {
425:
426: List servletElements = new ArrayList(1);
427:
428: Comment comment = new Comment(servletComment);
429: servletElements.add(comment);
430:
431: Element servletElement = new Element(SERVLET);
432: Element servletNameElement = new Element(SERVLET_NAME);
433: servletNameElement.addContent(servletName);
434: Element servletClassElement = new Element(SERVLET_CLASS);
435: servletClassElement.addContent(servletClass);
436: Element loadOnStartupElement = new Element(LOAD_ON_STARTUP);
437: loadOnStartupElement.addContent("2");
438:
439: servletElement.addContent(servletNameElement);
440: servletElement.addContent(servletClassElement);
441: servletElement.addContent(loadOnStartupElement);
442:
443: servletElements.add(servletElement);
444:
445: return servletElements;
446: }
447:
448: private static List genLoaderServletElements() {
449: List servletElements = new ArrayList(1);
450:
451: Comment comment = new Comment(loaderServletComment);
452: servletElements.add(comment);
453:
454: Element servletElement = new Element(SERVLET);
455: Element servletNameElement = new Element(SERVLET_NAME);
456: servletNameElement.addContent(loaderServletName);
457: Element servletClassElement = new Element(SERVLET_CLASS);
458: servletClassElement.addContent(loaderServletClass);
459: Element loadOnStartupElement = new Element(LOAD_ON_STARTUP);
460: loadOnStartupElement.addContent("1");
461:
462: servletElement.addContent(servletNameElement);
463: servletElement.addContent(servletClassElement);
464: servletElement.addContent(loadOnStartupElement);
465:
466: servletElements.add(servletElement);
467:
468: return servletElements;
469: }
470:
471: private static List genServletMappingElements() {
472:
473: List servletMappingElements = new ArrayList(1);
474:
475: Comment comment = new Comment(servletMappingComment);
476: servletMappingElements.add(comment);
477:
478: Element servletMappingElement = new Element(SERVLET_MAPPING);
479: Element servletNameElement = new Element(SERVLET_NAME);
480: servletNameElement.addContent(servletName);
481: Element urlPatternElement = new Element(URL_PATTERN);
482: urlPatternElement.addContent(servletMapping);
483: servletMappingElement.addContent(servletNameElement);
484: servletMappingElement.addContent(urlPatternElement);
485: servletMappingElements.add(servletMappingElement);
486:
487: return servletMappingElements;
488: }
489:
490: private static List genTaglibElements() {
491:
492: List taglibElements = new ArrayList(1);
493:
494: Comment comment = new Comment(taglibComment);
495: taglibElements.add(comment);
496:
497: Element taglibElement = new Element(TAGLIB);
498: Element taglibURIElement = new Element(TAGLIB_URI);
499: taglibURIElement.addContent(taglibURI);
500: Element taglibLocationElement = new Element(TAGLIB_LOCATION);
501: taglibLocationElement.addContent(taglibLocation);
502: taglibElement.addContent(taglibURIElement);
503: taglibElement.addContent(taglibLocationElement);
504: taglibElements.add(taglibElement);
505:
506: return taglibElements;
507:
508: }
509:
510: private static void removeElements(Element root,
511: Properties configProps) throws PortletDeployerException {
512: List children = root.getChildren();
513: List newchildren = new ArrayList();
514: Iterator itr = children.iterator();
515: while (itr.hasNext()) {
516: Element child = (Element) itr.next();
517: if (child.getName().equals(CONTEXT_PARAM)) {
518: String param = child.getChildTextTrim(PARAM_NAME);
519: if (!contextParams.contains(param)) {
520: //System.out.println("param retained=" + param);
521: newchildren.add(child);
522: }
523:
524: } else if (child.getName().equals(LISTENER)) {
525: String param = child.getChildTextTrim(LISTENER_CLASS);
526: if (!listenerClasses.contains(param)) {
527: //System.out.println("param retained=" + param);
528: newchildren.add(child);
529: }
530:
531: } else if (child.getName().equals(SERVLET)) {
532: String param = child.getChildTextTrim(SERVLET_NAME);
533: if (!param.equals(servletName)) {
534: //System.out.println("param retained=" + param);
535: newchildren.add(child);
536: }
537: } else {
538: newchildren.add(child);
539: }
540: }
541: Iterator it = root.getChildren().iterator();
542: List list = new ArrayList();
543: //need to copy names to avoid simoltanious update of iterator
544: while (it.hasNext())
545: list.add(((Element) it.next()).getName());
546: for (int count = 0; count < list.size(); count++) {
547: //using removeChild and not removeChildren to make sure
548: //next call to the same doesn't fails in case multiple
549: //child has same name
550: root.removeChild((String) list.get(count));
551: }
552: //root.setChildren(newchildren);
553: root.setContent(newchildren);
554: }
555:
556: }
|