You are viewing a plain text version of this content. The canonical link for it is here.
Posted to jetspeed-dev@portals.apache.org by wo...@apache.org on 2009/04/01 16:10:28 UTC

svn commit: r760898 - in /portals/jetspeed-2/portal/trunk: ./ components/jetspeed-cm/src/test/java/org/apache/jetspeed/cache/ components/jetspeed-portal/ components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/ components/jetspeed-...

Author: woonsan
Date: Wed Apr  1 14:10:20 2009
New Revision: 760898

URL: http://svn.apache.org/viewvc?rev=760898&view=rev
Log:
JS2-949: Adding basic createElement() and addProperty() implementation for head element contribution.
Now, all contributed head elements are stored in portlet content object as serializable elements.

Added:
    portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/util/DOMElementWriter.java   (with props)
    portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/util/DOMUtils.java   (with props)
    portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/java/org/apache/jetspeed/util/
    portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/java/org/apache/jetspeed/util/TestDOMUtils.java   (with props)
Modified:
    portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/test/java/org/apache/jetspeed/cache/TestContentCache.java
    portals/jetspeed-2/portal/trunk/components/jetspeed-portal/pom.xml
    portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/PortletContentImpl.java
    portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/container/impl/PortletRenderResponseContextImpl.java
    portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/container/impl/PortletResponseContextImpl.java
    portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/util/   (props changed)
    portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/aggregator/PortletContent.java
    portals/jetspeed-2/portal/trunk/pom.xml

Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/test/java/org/apache/jetspeed/cache/TestContentCache.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/test/java/org/apache/jetspeed/cache/TestContentCache.java?rev=760898&r1=760897&r2=760898&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/test/java/org/apache/jetspeed/cache/TestContentCache.java (original)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-cm/src/test/java/org/apache/jetspeed/cache/TestContentCache.java Wed Apr  1 14:10:20 2009
@@ -16,8 +16,10 @@
  */
 package org.apache.jetspeed.cache;
 
+import java.io.NotSerializableException;
 import java.io.PrintWriter;
 import java.security.Principal;
+import java.util.Collection;
 import java.util.LinkedList;
 import java.util.List;
 
@@ -30,6 +32,7 @@
 import org.apache.jetspeed.cache.impl.EhPortletContentCacheImpl;
 import org.apache.jetspeed.cache.impl.JetspeedCacheKeyGenerator;
 import org.apache.jetspeed.mockobjects.request.MockRequestContext;
+import org.w3c.dom.Element;
 
 import com.mockrunner.mock.web.MockHttpServletRequest;
 import com.mockrunner.mock.web.MockHttpServletResponse;
@@ -388,6 +391,20 @@
             // TODO Auto-generated method stub
             
         }
+
+
+        public void addHeadElement(Element element, String keyHint) throws NotSerializableException
+        {
+            // TODO Auto-generated method stub
+            
+        }
+
+
+        public Collection<Element> getHeadElements()
+        {
+            // TODO Auto-generated method stub
+            return null;
+        }
     }
         
 }

Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-portal/pom.xml
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-portal/pom.xml?rev=760898&r1=760897&r2=760898&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-portal/pom.xml (original)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-portal/pom.xml Wed Apr  1 14:10:20 2009
@@ -134,7 +134,14 @@
             <groupId>net.sf.ehcache</groupId>
             <artifactId>ehcache</artifactId>
         </dependency>
-
+        <dependency>
+            <groupId>jaxen</groupId>
+            <artifactId>jaxen</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>dom4j</groupId>
+            <artifactId>dom4j</artifactId>
+        </dependency>
         <dependency>
         	<groupId>asm</groupId>
         	<artifactId>asm</artifactId>

Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/PortletContentImpl.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/PortletContentImpl.java?rev=760898&r1=760897&r2=760898&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/PortletContentImpl.java (original)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/aggregator/impl/PortletContentImpl.java Wed Apr  1 14:10:20 2009
@@ -17,11 +17,19 @@
 package org.apache.jetspeed.aggregator.impl;
 
 import java.io.CharArrayWriter;
+import java.io.NotSerializableException;
 import java.io.PrintWriter;
+import java.io.Serializable;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.Map;
 
 import org.apache.jetspeed.aggregator.PortletContent;
 import org.apache.jetspeed.aggregator.PortletRenderer;
 import org.apache.jetspeed.cache.ContentCacheKey;
+import org.apache.jetspeed.util.DOMUtils;
+import org.w3c.dom.Element;
 
 
 public class PortletContentImpl implements PortletContent
@@ -34,6 +42,7 @@
     private String title;
     private String contentType;
     private PortletRenderer renderer = null;
+    private Map<String, Element> headElements = null;
     
     PortletContentImpl()
     {
@@ -176,4 +185,54 @@
             cw.reset();
         }
     }
+
+    public void addHeadElement(Element element, String keyHint) throws NotSerializableException
+    {
+        if (this.headElements == null)
+        {
+            this.headElements = new HashMap<String, Element>();
+        }
+
+        if (element == null)
+        {
+            if (keyHint != null)
+            {
+                this.headElements.remove(keyHint);
+            }
+            
+            return;
+        }
+        
+        if (!(element instanceof Serializable))
+        {
+            throw new NotSerializableException("The element is not serializable.");
+        }
+        
+        if (keyHint == null)
+        {
+            if (element instanceof org.dom4j.Element) 
+            {
+                keyHint = DOMUtils.stringifyElement((org.dom4j.Element) element);
+            }
+            else
+            {
+                keyHint = DOMUtils.stringifyElement(element);
+            }
+        }
+
+        this.headElements.put(keyHint, element);
+    }
+
+    public Collection<Element> getHeadElements()
+    {
+        if (this.headElements != null) 
+        {
+            return this.headElements.values();
+        } 
+        else 
+        {
+            return Collections.emptyList();
+        }
+    }
+    
 }
\ No newline at end of file

Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/container/impl/PortletRenderResponseContextImpl.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/container/impl/PortletRenderResponseContextImpl.java?rev=760898&r1=760897&r2=760898&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/container/impl/PortletRenderResponseContextImpl.java (original)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/container/impl/PortletRenderResponseContextImpl.java Wed Apr  1 14:10:20 2009
@@ -18,19 +18,24 @@
 package org.apache.jetspeed.container.impl;
 
 import java.io.IOException;
+import java.io.NotSerializableException;
 import java.io.OutputStream;
 import java.io.PrintWriter;
+import java.io.Serializable;
 import java.util.Collection;
 
+import javax.portlet.MimeResponse;
 import javax.portlet.PortletMode;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
+import org.apache.jetspeed.aggregator.PortletContent;
+import org.apache.jetspeed.container.PortletWindow;
+import org.apache.jetspeed.util.DOMUtils;
 import org.apache.pluto.container.PortletContainer;
 import org.apache.pluto.container.PortletRenderResponseContext;
 import org.apache.pluto.container.util.PrintWriterServletOutputStream;
-import org.apache.jetspeed.aggregator.PortletContent;
-import org.apache.jetspeed.container.PortletWindow;
+import org.w3c.dom.Element;
 
 /**
  * @version $Id$
@@ -124,5 +129,52 @@
         {
             portletContent.setTitle(title);
         }
-    } 
+    }
+    
+    @Override
+    public void addProperty(String key, Element element)
+    {
+        if (MimeResponse.MARKUP_HEAD_ELEMENT.equals(key))
+        {
+            Element headElement = null;
+            
+            if (element instanceof Serializable)
+            {
+                headElement = element;
+            }
+            else
+            {
+                headElement = DOMUtils.convertToSerializableElement(element);
+            }
+            
+            try
+            {
+                // ID attribute of element is used as keyHint for the head element if available.
+                this.portletContent.addHeadElement(headElement, getIdAttribute(element));
+            }
+            catch (NotSerializableException e)
+            {
+            }
+        }
+        else
+        {
+            super.addProperty(key, element);
+        }
+    }
+    
+    private String getIdAttribute(Element element)
+    {
+        String value = null;
+        
+        if (element.hasAttribute("ID"))
+            value = element.getAttribute("ID");
+        else if (element.hasAttribute("id"))
+            value = element.getAttribute("id");
+        else if (element.hasAttribute("Id"))
+            value = element.getAttribute("Id");
+        else if (element.hasAttribute("iD"))
+            value = element.getAttribute("iD");
+        
+        return value;
+    }
 }

Modified: portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/container/impl/PortletResponseContextImpl.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/container/impl/PortletResponseContextImpl.java?rev=760898&r1=760897&r2=760898&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/container/impl/PortletResponseContextImpl.java (original)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/container/impl/PortletResponseContextImpl.java Wed Apr  1 14:10:20 2009
@@ -24,6 +24,7 @@
 import org.apache.jetspeed.container.PortletWindow;
 import org.apache.jetspeed.container.providers.ResourceURLProviderImpl;
 import org.apache.jetspeed.request.JetspeedRequestContext;
+import org.apache.jetspeed.util.DOMUtils;
 import org.apache.pluto.container.PortletContainer;
 import org.apache.pluto.container.PortletResponseContext;
 import org.apache.pluto.container.ResourceURLProvider;
@@ -102,8 +103,7 @@
     
     public Element createElement(String tagName) throws DOMException
     {
-        // TODO: create DOM element in a more optimized way.
-        return null;
+        return DOMUtils.createSerializableElement(tagName);
     }
 
     public void close()

Propchange: portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/util/
------------------------------------------------------------------------------
--- svn:ignore (original)
+++ svn:ignore Wed Apr  1 14:10:20 2009
@@ -1,2 +1,2 @@
-target
+target
 surefire*.properties

Added: portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/util/DOMElementWriter.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/util/DOMElementWriter.java?rev=760898&view=auto
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/util/DOMElementWriter.java (added)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/util/DOMElementWriter.java Wed Apr  1 14:10:20 2009
@@ -0,0 +1,572 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jetspeed.util;
+
+import java.io.IOException;
+import java.io.OutputStream;
+import java.io.OutputStreamWriter;
+import java.io.Writer;
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.Iterator;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+
+/**
+ * Writes a DOM tree to a given Writer.
+ * warning: this utility currently does not declare XML Namespaces.
+ * <p>Utility class used by {@link org.apache.jetspeed.util.DOMUtils}.</p>
+ */
+public class DOMElementWriter {
+
+    private static final int HEX = 16;
+
+    /** prefix for generated prefixes */
+    private static final String NS = "ns";
+
+    /** xml declaration is on by default */
+    private boolean xmlDeclaration = true;
+
+    /**
+     * XML Namespaces are ignored by default.
+     */
+    private XmlNamespacePolicy namespacePolicy = XmlNamespacePolicy.IGNORE;
+
+    /**
+     * Map (URI to prefix) of known namespaces.
+     */
+    private HashMap nsPrefixMap = new HashMap();
+
+    /**
+     * Number of generated prefix to use next.
+     */
+    private int nextPrefix = 0;
+
+    /**
+     * Map (Element to URI) of namespaces defined on a given element.
+     */
+    private HashMap nsURIByElement = new HashMap();
+
+    /**
+     * Whether namespaces should be ignored for elements and attributes.
+     */
+    public static class XmlNamespacePolicy {
+        private boolean qualifyElements;
+        private boolean qualifyAttributes;
+
+        /**
+         * Ignores namespaces for elements and attributes, the default.
+         */
+        public static final XmlNamespacePolicy IGNORE =
+            new XmlNamespacePolicy(false, false);
+
+        /**
+         * Ignores namespaces for attributes.
+         */
+        public static final XmlNamespacePolicy ONLY_QUALIFY_ELEMENTS =
+            new XmlNamespacePolicy(true, false);
+
+        /**
+         * Qualifies namespaces for elements and attributes.
+         */
+        public static final XmlNamespacePolicy QUALIFY_ALL =
+            new XmlNamespacePolicy(true, true);
+
+        /**
+         * @param qualifyElements whether to qualify elements
+         * @param qualifyAttributes whether to qualify elements
+         */
+        public XmlNamespacePolicy(boolean qualifyElements,
+                                  boolean qualifyAttributes) {
+            this.qualifyElements = qualifyElements;
+            this.qualifyAttributes = qualifyAttributes;
+        }
+    }
+
+    /**
+     * Create an element writer.
+     * The ?xml? declaration will be included, namespaces ignored.
+     */
+    public DOMElementWriter() {
+    }
+
+    /**
+     * Create an element writer
+     * XML namespaces will be ignored.
+     * @param xmlDeclaration flag to indicate whether the ?xml? declaration
+     * should be included.
+     */
+    public DOMElementWriter(boolean xmlDeclaration) {
+        this(xmlDeclaration, XmlNamespacePolicy.IGNORE);
+    }
+
+    /**
+     * Create an element writer
+     * XML namespaces will be ignored.
+     * @param xmlDeclaration flag to indicate whether the ?xml? declaration
+     * should be included.
+     * @param namespacePolicy the policy to use.
+     */
+    public DOMElementWriter(boolean xmlDeclaration,
+                            XmlNamespacePolicy namespacePolicy) {
+        this.xmlDeclaration = xmlDeclaration;
+        this.namespacePolicy = namespacePolicy;
+    }
+
+    private static String lSep = System.getProperty("line.separator");
+
+    // CheckStyle:VisibilityModifier OFF - bc
+    /**
+     * Don't try to be too smart but at least recognize the predefined
+     * entities.
+     */
+    protected String[] knownEntities = {"gt", "amp", "lt", "apos", "quot"};
+    // CheckStyle:VisibilityModifier ON
+
+
+    /**
+     * Writes a DOM tree to a stream in UTF8 encoding. Note that
+     * it prepends the &lt;?xml version='1.0' encoding='UTF-8'?&gt; if
+     * the xmlDeclaration field is true.
+     * The indent number is set to 0 and a 2-space indent.
+     * @param root the root element of the DOM tree.
+     * @param out the outputstream to write to.
+     * @throws IOException if an error happens while writing to the stream.
+     */
+    public void write(Element root, OutputStream out) throws IOException {
+        Writer wri = new OutputStreamWriter(out, "UTF8");
+        writeXMLDeclaration(wri);
+        write(root, wri, 0, "  ");
+        wri.flush();
+    }
+
+    /**
+     * Writes the XML declaration if xmlDeclaration is true.
+     * @param wri the writer to write to.
+     * @throws IOException if there is an error.
+     */
+    public void writeXMLDeclaration(Writer wri) throws IOException {
+        if (xmlDeclaration) {
+            wri.write("<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n");
+        }
+    }
+
+    /**
+     * Writes a DOM tree to a stream.
+     *
+     * @param element the Root DOM element of the tree
+     * @param out where to send the output
+     * @param indent number of
+     * @param indentWith string that should be used to indent the
+     * corresponding tag.
+     * @throws IOException if an error happens while writing to the stream.
+     */
+    public void write(Element element, Writer out, int indent,
+                      String indentWith)
+        throws IOException {
+
+        // Write child elements and text
+        NodeList children = element.getChildNodes();
+        boolean hasChildren = (children.getLength() > 0);
+        boolean hasChildElements = false;
+        openElement(element, out, indent, indentWith, hasChildren);
+
+        if (hasChildren) {
+            for (int i = 0; i < children.getLength(); i++) {
+                Node child = children.item(i);
+
+                switch (child.getNodeType()) {
+
+                case Node.ELEMENT_NODE:
+                    hasChildElements = true;
+                    if (i == 0) {
+                        out.write(lSep);
+                    }
+                    write((Element) child, out, indent + 1, indentWith);
+                    break;
+
+                case Node.TEXT_NODE:
+                    out.write(encode(child.getNodeValue()));
+                    break;
+
+                case Node.COMMENT_NODE:
+                    out.write("<!--");
+                    out.write(encode(child.getNodeValue()));
+                    out.write("-->");
+                    break;
+
+                case Node.CDATA_SECTION_NODE:
+                    out.write("<![CDATA[");
+                    out.write(encodedata(((Text) child).getData()));
+                    out.write("]]>");
+                    break;
+
+                case Node.ENTITY_REFERENCE_NODE:
+                    out.write('&');
+                    out.write(child.getNodeName());
+                    out.write(';');
+                    break;
+
+                case Node.PROCESSING_INSTRUCTION_NODE:
+                    out.write("<?");
+                    out.write(child.getNodeName());
+                    String data = child.getNodeValue();
+                    if (data != null && data.length() > 0) {
+                        out.write(' ');
+                        out.write(data);
+                    }
+                    out.write("?>");
+                    break;
+                default:
+                    // Do nothing
+                }
+            }
+            closeElement(element, out, indent, indentWith, hasChildElements);
+        }
+    }
+
+    /**
+     * Writes the opening tag - including all attributes -
+     * corresponding to a DOM element.
+     *
+     * @param element the DOM element to write
+     * @param out where to send the output
+     * @param indent number of
+     * @param indentWith string that should be used to indent the
+     * corresponding tag.
+     * @throws IOException if an error happens while writing to the stream.
+     */
+    public void openElement(Element element, Writer out, int indent,
+                            String indentWith)
+        throws IOException {
+        openElement(element, out, indent, indentWith, true);
+    }
+
+    /**
+     * Writes the opening tag - including all attributes -
+     * corresponding to a DOM element.
+     *
+     * @param element the DOM element to write
+     * @param out where to send the output
+     * @param indent number of
+     * @param indentWith string that should be used to indent the
+     * corresponding tag.
+     * @param hasChildren whether this element has children.
+     * @throws IOException if an error happens while writing to the stream.
+     */
+    public void openElement(Element element, Writer out, int indent,
+                            String indentWith, boolean hasChildren)
+        throws IOException {
+        // Write indent characters
+        for (int i = 0; i < indent; i++) {
+            out.write(indentWith);
+        }
+
+        // Write element
+        out.write("<");
+        if (namespacePolicy.qualifyElements) {
+            String uri = getNamespaceURI(element);
+            String prefix = (String) nsPrefixMap.get(uri);
+            if (prefix == null) {
+                if (nsPrefixMap.isEmpty()) {
+                    // steal default namespace
+                    prefix = "";
+                } else {
+                    prefix = NS + (nextPrefix++);
+                }
+                nsPrefixMap.put(uri, prefix);
+                addNSDefinition(element, uri);
+            }
+            if (!"".equals(prefix)) {
+                out.write(prefix);
+                out.write(":");
+            }
+        }
+        out.write(element.getTagName());
+
+        // Write attributes
+        NamedNodeMap attrs = element.getAttributes();
+        for (int i = 0; i < attrs.getLength(); i++) {
+            Attr attr = (Attr) attrs.item(i);
+            out.write(" ");
+            if (namespacePolicy.qualifyAttributes) {
+                String uri = getNamespaceURI(attr);
+                String prefix = (String) nsPrefixMap.get(uri);
+                if (prefix == null) {
+                    prefix = NS + (nextPrefix++);
+                    nsPrefixMap.put(uri, prefix);
+                    addNSDefinition(element, uri);
+                }
+                out.write(prefix);
+                out.write(":");
+            }
+            out.write(attr.getName());
+            out.write("=\"");
+            out.write(encode(attr.getValue()));
+            out.write("\"");
+        }
+
+        // write namespace declarations
+        ArrayList al = (ArrayList) nsURIByElement.get(element);
+        if (al != null) {
+            Iterator iter = al.iterator();
+            while (iter.hasNext()) {
+                String uri = (String) iter.next();
+                String prefix = (String) nsPrefixMap.get(uri);
+                out.write(" xmlns");
+                if (!"".equals(prefix)) {
+                    out.write(":");
+                    out.write(prefix);
+                }
+                out.write("=\"");
+                out.write(uri);
+                out.write("\"");
+            }
+        }
+
+        if (hasChildren) {
+            out.write(">");
+        } else {
+            removeNSDefinitions(element);
+            out.write(" />");
+            out.write(lSep);
+            out.flush();
+        }
+    }
+
+    /**
+     * Writes a DOM tree to a stream.
+     *
+     * @param element the Root DOM element of the tree
+     * @param out where to send the output
+     * @param indent number of
+     * @param indentWith string that should be used to indent the
+     * corresponding tag.
+     * @param hasChildren if true indent.
+     * @throws IOException if an error happens while writing to the stream.
+     */
+    public void closeElement(Element element, Writer out, int indent,
+                             String indentWith, boolean hasChildren)
+        throws IOException {
+        // If we had child elements, we need to indent before we close
+        // the element, otherwise we're on the same line and don't need
+        // to indent
+        if (hasChildren) {
+            for (int i = 0; i < indent; i++) {
+                out.write(indentWith);
+            }
+        }
+
+        // Write element close
+        out.write("</");
+        if (namespacePolicy.qualifyElements) {
+            String uri = getNamespaceURI(element);
+            String prefix = (String) nsPrefixMap.get(uri);
+            if (prefix != null && !"".equals(prefix)) {
+                out.write(prefix);
+                out.write(":");
+            }
+            removeNSDefinitions(element);
+        }
+        out.write(element.getTagName());
+        out.write(">");
+        out.write(lSep);
+        out.flush();
+    }
+
+    /**
+     * Escape &lt;, &gt; &amp; &apos;, &quot; as their entities and
+     * drop characters that are illegal in XML documents.
+     * @param value the string to encode.
+     * @return the encoded string.
+     */
+    public String encode(String value) {
+        StringBuffer sb = new StringBuffer();
+        int len = value.length();
+        for (int i = 0; i < len; i++) {
+            char c = value.charAt(i);
+            switch (c) {
+            case '<':
+                sb.append("&lt;");
+                break;
+            case '>':
+                sb.append("&gt;");
+                break;
+            case '\'':
+                sb.append("&apos;");
+                break;
+            case '\"':
+                sb.append("&quot;");
+                break;
+            case '&':
+                int nextSemi = value.indexOf(";", i);
+                if (nextSemi < 0
+                    || !isReference(value.substring(i, nextSemi + 1))) {
+                    sb.append("&amp;");
+                } else {
+                    sb.append('&');
+                }
+                break;
+            default:
+                if (isLegalCharacter(c)) {
+                    sb.append(c);
+                }
+                break;
+            }
+        }
+        return sb.substring(0);
+    }
+
+    /**
+     * Drop characters that are illegal in XML documents.
+     *
+     * <p>Also ensure that we are not including an <code>]]&gt;</code>
+     * marker by replacing that sequence with
+     * <code>&amp;#x5d;&amp;#x5d;&amp;gt;</code>.</p>
+     *
+     * <p>See XML 1.0 2.2 <a
+     * href="http://www.w3.org/TR/1998/REC-xml-19980210#charsets">
+     * http://www.w3.org/TR/1998/REC-xml-19980210#charsets</a> and
+     * 2.7 <a
+     * href="http://www.w3.org/TR/1998/REC-xml-19980210#sec-cdata-sect">http://www.w3.org/TR/1998/REC-xml-19980210#sec-cdata-sect</a>.</p>
+     * @param value the value to be encoded.
+     * @return the encoded value.
+
+     */
+    public String encodedata(final String value) {
+        StringBuffer sb = new StringBuffer();
+        int len = value.length();
+        for (int i = 0; i < len; ++i) {
+            char c = value.charAt(i);
+            if (isLegalCharacter(c)) {
+                sb.append(c);
+            }
+        }
+
+        String result = sb.substring(0);
+        int cdEnd = result.indexOf("]]>");
+        while (cdEnd != -1) {
+            sb.setLength(cdEnd);
+            // CheckStyle:MagicNumber OFF
+            sb.append("&#x5d;&#x5d;&gt;")
+                .append(result.substring(cdEnd + 3));
+            // CheckStyle:MagicNumber ON
+            result = sb.substring(0);
+            cdEnd = result.indexOf("]]>");
+        }
+
+        return result;
+    }
+
+    /**
+     * Is the given argument a character or entity reference?
+     * @param ent the value to be checked.
+     * @return true if it is an entity.
+     */
+    public boolean isReference(String ent) {
+        if (!(ent.charAt(0) == '&') || !ent.endsWith(";")) {
+            return false;
+        }
+
+        if (ent.charAt(1) == '#') {
+            if (ent.charAt(2) == 'x') {
+                try {
+                    // CheckStyle:MagicNumber OFF
+                    Integer.parseInt(ent.substring(3, ent.length() - 1), HEX);
+                    // CheckStyle:MagicNumber ON
+                    return true;
+                } catch (NumberFormatException nfe) {
+                    return false;
+                }
+            } else {
+                try {
+                    Integer.parseInt(ent.substring(2, ent.length() - 1));
+                    return true;
+                } catch (NumberFormatException nfe) {
+                    return false;
+                }
+            }
+        }
+
+        String name = ent.substring(1, ent.length() - 1);
+        for (int i = 0; i < knownEntities.length; i++) {
+            if (name.equals(knownEntities[i])) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Is the given character allowed inside an XML document?
+     *
+     * <p>See XML 1.0 2.2 <a
+     * href="http://www.w3.org/TR/1998/REC-xml-19980210#charsets">
+     * http://www.w3.org/TR/1998/REC-xml-19980210#charsets</a>.</p>
+     * @param c the character to test.
+     * @return true if the character is allowed.
+     */
+    public boolean isLegalCharacter(char c) {
+        // CheckStyle:MagicNumber OFF
+        if (c == 0x9 || c == 0xA || c == 0xD) {
+            return true;
+        } else if (c < 0x20) {
+            return false;
+        } else if (c <= 0xD7FF) {
+            return true;
+        } else if (c < 0xE000) {
+            return false;
+        } else if (c <= 0xFFFD) {
+            return true;
+        }
+        // CheckStyle:MagicNumber ON
+        return false;
+    }
+
+    private void removeNSDefinitions(Element element) {
+        ArrayList al = (ArrayList) nsURIByElement.get(element);
+        if (al != null) {
+            Iterator iter = al.iterator();
+            while (iter.hasNext()) {
+                nsPrefixMap.remove(iter.next());
+            }
+            nsURIByElement.remove(element);
+        }
+    }
+
+    private void addNSDefinition(Element element, String uri) {
+        ArrayList al = (ArrayList) nsURIByElement.get(element);
+        if (al == null) {
+            al = new ArrayList();
+            nsURIByElement.put(element, al);
+        }
+        al.add(uri);
+    }
+
+    private static String getNamespaceURI(Node n) {
+        String uri = n.getNamespaceURI();
+        if (uri == null) {
+            // FIXME: Is "No Namespace is Empty Namespace" really OK?
+            uri = "";
+        }
+        return uri;
+    }
+}

Propchange: portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/util/DOMElementWriter.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/util/DOMElementWriter.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/util/DOMElementWriter.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/util/DOMUtils.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/util/DOMUtils.java?rev=760898&view=auto
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/util/DOMUtils.java (added)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/util/DOMUtils.java Wed Apr  1 14:10:20 2009
@@ -0,0 +1,174 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jetspeed.util;
+
+import java.io.IOException;
+import java.io.StringWriter;
+
+import org.dom4j.dom.DOMCDATA;
+import org.dom4j.dom.DOMComment;
+import org.dom4j.dom.DOMElement;
+import org.dom4j.dom.DOMText;
+import org.dom4j.io.OutputFormat;
+import org.dom4j.io.XMLWriter;
+import org.w3c.dom.Attr;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+
+public class DOMUtils
+{
+    
+    public static final int DEFAULT_ELEMENT_STRINGIFYING_BUFFER_SIZE = 80;
+    public static final int DEFAULT_INDENT = 0;
+    public static final String DEFAULT_INDENT_WITH = "\t";
+    
+    private DOMUtils()
+    {
+    }
+    
+    public static org.w3c.dom.Element createSerializableElement(String tagName)
+    {
+        return new DOMElement(tagName)
+        {
+            private static final long serialVersionUID = 1L;
+
+            public void setTextContent(String textContent)
+            {
+                setText(textContent);
+            }
+            
+            public String getTextContent()
+            {
+                return getText();
+            }
+        };
+    }
+    
+    public static org.w3c.dom.Element convertToSerializableElement(org.w3c.dom.Element element)
+    {
+        return (org.w3c.dom.Element) convertElement(element);
+    }
+    
+    public static org.dom4j.Element convertElement(org.w3c.dom.Element element)
+    {
+        DOMElement domElement = (DOMElement) createSerializableElement(element.getNodeName());
+        
+        NamedNodeMap attrs = element.getAttributes();
+        
+        for (int i = 0; i < attrs.getLength(); i++) 
+        {
+            Attr attr = (Attr) attrs.item(i);
+            domElement.setAttribute(attr.getName(), attr.getValue());
+        }
+        
+        NodeList children = element.getChildNodes();
+        boolean hasChildren = (children.getLength() > 0);
+
+        if (hasChildren) 
+        {
+            for (int i = 0; i < children.getLength(); i++) 
+            {
+                Node child = children.item(i);
+
+                switch (child.getNodeType()) 
+                {
+                case Node.ELEMENT_NODE:
+                    domElement.add(convertElement((org.w3c.dom.Element) child));
+                    break;
+                case Node.TEXT_NODE:
+                    domElement.add(new DOMText(child.getNodeValue()));
+                    break;
+                case Node.COMMENT_NODE:
+                    domElement.add(new DOMComment(child.getNodeValue()));
+                    break;
+                case Node.CDATA_SECTION_NODE:
+                    domElement.add(new DOMCDATA(child.getNodeValue()));
+                    break;
+                default:
+                    // Do not support entity reference node and processing instruction node.
+                }
+            }
+        }
+        
+        return domElement;
+    }
+
+    public static String stringifyElement(org.w3c.dom.Element element)
+    {
+        return stringifyElement(element, DEFAULT_ELEMENT_STRINGIFYING_BUFFER_SIZE, DEFAULT_INDENT, DEFAULT_INDENT_WITH);
+    }
+
+    public static String stringifyElement(org.w3c.dom.Element element, int initialBufferSize, int indent, String indentWith)
+    {
+        String stringified = null;
+        StringWriter writer = new StringWriter(initialBufferSize);
+        
+        try
+        {
+            DOMElementWriter domWriter = new DOMElementWriter();
+            domWriter.write(element, writer, indent, indentWith);
+        }
+        catch (IOException e)
+        {
+        }
+
+        stringified = writer.toString();
+        return stringified;
+    }
+    
+    public static String stringifyElement(org.dom4j.Element element)
+    {
+        return stringifyElement(element, DEFAULT_ELEMENT_STRINGIFYING_BUFFER_SIZE, DEFAULT_INDENT_WITH);
+    }
+    
+    public static String stringifyElement(org.dom4j.Element element, int initialBufferSize, String indentWith)
+    {
+        OutputFormat outputFormat = new OutputFormat();
+        outputFormat.setIndent(indentWith);
+        return stringifyElement(element, initialBufferSize, outputFormat);
+    }
+    
+    public static String stringifyElement(org.dom4j.Element element, int initialBufferSize, OutputFormat outputFormat)
+    {
+        String stringified = null;
+        StringWriter writer = new StringWriter(initialBufferSize);
+        XMLWriter xmlWriter = null;
+        
+        try
+        {
+            xmlWriter = new XMLWriter(writer, outputFormat);
+            xmlWriter.write(element);
+            xmlWriter.flush();
+            xmlWriter.close();
+        }
+        catch (IOException e)
+        {
+        }
+        finally
+        {
+            if (xmlWriter != null)
+            {
+                try { xmlWriter.close(); } catch (IOException ce) { }
+            }
+        }
+        
+        stringified = writer.toString();
+        return stringified;
+    }
+    
+}

Propchange: portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/util/DOMUtils.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/util/DOMUtils.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/main/java/org/apache/jetspeed/util/DOMUtils.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Added: portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/java/org/apache/jetspeed/util/TestDOMUtils.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/java/org/apache/jetspeed/util/TestDOMUtils.java?rev=760898&view=auto
==============================================================================
--- portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/java/org/apache/jetspeed/util/TestDOMUtils.java (added)
+++ portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/java/org/apache/jetspeed/util/TestDOMUtils.java Wed Apr  1 14:10:20 2009
@@ -0,0 +1,115 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The ASF licenses this file to You under the Apache License, Version 2.0
+ * (the "License"); you may not use this file except in compliance with
+ * the License.  You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+package org.apache.jetspeed.util;
+
+import java.io.Serializable;
+
+import javax.xml.parsers.DocumentBuilder;
+import javax.xml.parsers.DocumentBuilderFactory;
+
+import junit.framework.TestCase;
+
+import org.apache.commons.lang.SerializationUtils;
+import org.w3c.dom.CDATASection;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+
+public class TestDOMUtils extends TestCase
+{
+
+    public void testW3CDOMElement() throws Exception
+    {
+        DocumentBuilderFactory dbfac = DocumentBuilderFactory.newInstance();
+        DocumentBuilder docBuilder = dbfac.newDocumentBuilder();
+        Document doc = docBuilder.newDocument();
+        Element element = doc.createElement("script");
+        element.setAttribute("id", "my-test-javascript");
+        element.setAttribute("type", "text/javascript");
+        element.setTextContent("alert('<Hello, World!>');");
+        Element child = doc.createElement("source");
+        child.setAttribute("id", "my-test-javascript-source");
+        child.setTextContent("source is available.");
+        element.appendChild(child);
+        
+        String stringified = DOMUtils.stringifyElement(element);
+        System.out.println("stringified: " + stringified);
+        assertTrue("element name is different.", stringified.contains("<script "));
+        assertTrue("id attribute does not exist.", stringified.contains("id=\"my-test-javascript\""));
+        assertTrue("type attribute does not exist.", stringified.contains("type=\"text/javascript\""));
+        assertTrue("the text content is wrong.", stringified.contains("alert("));
+        assertTrue("the text content is wrong.", stringified.contains("Hello, World!"));
+        assertTrue("the child element is wrong.", stringified.contains("<source id=\"my-test-javascript-source\">source is available.</source>"));
+        
+        Element converted = (Element) DOMUtils.convertElement(element);
+        assertTrue("converted element is not serializable!", converted instanceof Serializable);
+        assertEquals("converted element name is wrong.", element.getNodeName(), converted.getNodeName());
+        
+        Element deserialized = (Element) SerializationUtils.clone((Serializable) converted);
+        assertEquals("deserialized element name is wrong.", converted.getNodeName(), deserialized.getNodeName());
+        stringified = DOMUtils.stringifyElement((org.dom4j.Element) deserialized);
+        System.out.println("deserialized element's stringified: " + stringified);
+        assertTrue("deserialized element name is different.", stringified.contains("<script "));
+        assertTrue("id attribute does not exist.", stringified.contains("id=\"my-test-javascript\""));
+        assertTrue("type attribute does not exist.", stringified.contains("type=\"text/javascript\""));
+        assertTrue("the text content is wrong.", stringified.contains("alert("));
+        assertTrue("the text content is wrong.", stringified.contains("Hello, World!"));
+        assertTrue("the child element is wrong.", stringified.contains("<source id=\"my-test-javascript-source\">source is available.</source>"));
+        
+        stringified = DOMUtils.stringifyElement((org.dom4j.Element) converted);
+        System.out.println("converted element's stringified: " + stringified);
+        assertTrue("converted element name is different.", stringified.contains("<script "));
+        assertTrue("id attribute does not exist.", stringified.contains("id=\"my-test-javascript\""));
+        assertTrue("type attribute does not exist.", stringified.contains("type=\"text/javascript\""));
+        assertTrue("the text content is wrong.", stringified.contains("alert("));
+        assertTrue("the text content is wrong.", stringified.contains("Hello, World!"));
+        assertTrue("the child element is wrong.", stringified.contains("<source id=\"my-test-javascript-source\">source is available.</source>"));
+        
+        element = doc.createElement("script");
+        element.setAttribute("id", "my-test-javascript");
+        element.setAttribute("type", "text/javascript");
+        CDATASection cdataSection = doc.createCDATASection("alert('<Hello, World!>');");
+        element.appendChild(cdataSection);
+        child = doc.createElement("source");
+        child.setAttribute("id", "my-test-javascript-source");
+        child.setTextContent("source is available.");
+        element.appendChild(child);
+        
+        stringified = DOMUtils.stringifyElement(element);
+        System.out.println("stringified: " + stringified);
+        assertTrue("the text content is wrong.", stringified.contains("<![CDATA[alert("));
+        assertTrue("the text content is wrong.", stringified.contains("Hello, World!"));
+        assertTrue("the child element is wrong.", stringified.contains("<source id=\"my-test-javascript-source\">source is available.</source>"));
+    }
+
+    public void testDOM4JElement() throws Exception
+    {
+        org.w3c.dom.Element element = DOMUtils.createSerializableElement("script");
+        element.setAttribute("id", "my-test-javascript");
+        element.setAttribute("type", "text/javascript");
+        element.setTextContent("alert('<Hello, World!>');");
+        
+        String stringified = DOMUtils.stringifyElement((org.dom4j.Element) element);
+        
+        System.out.println("stringified: " + stringified);
+        assertTrue("element name is different.", stringified.contains("<script "));
+        assertTrue("id attribute does not exist.", stringified.contains("id=\"my-test-javascript\""));
+        assertTrue("type attribute does not exist.", stringified.contains("type=\"text/javascript\""));
+        assertTrue("the text content is wrong.", stringified.contains("alert("));
+        assertTrue("the text content is wrong.", stringified.contains("Hello, World!"));
+    }
+    
+}

Propchange: portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/java/org/apache/jetspeed/util/TestDOMUtils.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/java/org/apache/jetspeed/util/TestDOMUtils.java
------------------------------------------------------------------------------
    svn:keywords = Id

Propchange: portals/jetspeed-2/portal/trunk/components/jetspeed-portal/src/test/java/org/apache/jetspeed/util/TestDOMUtils.java
------------------------------------------------------------------------------
    svn:mime-type = text/plain

Modified: portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/aggregator/PortletContent.java
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/aggregator/PortletContent.java?rev=760898&r1=760897&r2=760898&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/aggregator/PortletContent.java (original)
+++ portals/jetspeed-2/portal/trunk/jetspeed-api/src/main/java/org/apache/jetspeed/aggregator/PortletContent.java Wed Apr  1 14:10:20 2009
@@ -16,9 +16,12 @@
 */
 package org.apache.jetspeed.aggregator;
 
+import java.io.NotSerializableException;
 import java.io.PrintWriter;
+import java.util.Collection;
 
 import org.apache.jetspeed.cache.ContentCacheKey;
+import org.w3c.dom.Element;
 
 /**
  * <p>
@@ -68,6 +71,12 @@
      * @return
      */
     int getExpiration();
+    
+    /**
+     * Sets the expiration setting for this content.
+     * 
+     * @param expiration
+     */
     void setExpiration(int expiration);
     
     /**
@@ -90,10 +99,47 @@
      */
     void setTitle(String title);
     
+    /**
+     * Gets the content type of this portlet content.
+     * 
+     * @return
+     */
     String getContentType();
+    
+    /**
+     * Sets the content type of this portlet content.
+     * 
+     * @param contentType
+     */
     void setContentType(String contentType);
+
+    /**
+     * Adds an header element to be contributed to the page.
+     * If keyHint argument is provided and if a header element 
+     * with the provided key hint already exists, then 
+     * the element will be overwritten to the item.
+     * If the element is null and keyHint is not null, 
+     * the element with the keyHint is removed from the response.
+     * If the element is not null and keyHint is null,
+     * then the keyHint will be automatically generated by the element content. 
+     * Meanwhile, the element should implement java.io.Serializable.
+     * Otherwise it will throw a java.io.NotSerializableException.
+     * 
+     * @param element
+     * @param keyHint
+     * @throws NotSerializableException
+     */
+    void addHeadElement(Element element, String keyHint) throws NotSerializableException;
+    
+    /**
+     * Retrieves header element list to be contributed to the page.
+     * 
+     * @return List with head element items
+     */
+    Collection<Element> getHeadElements(); 
     
     void reset();
+    
     void resetBuffer();
     
     /**

Modified: portals/jetspeed-2/portal/trunk/pom.xml
URL: http://svn.apache.org/viewvc/portals/jetspeed-2/portal/trunk/pom.xml?rev=760898&r1=760897&r2=760898&view=diff
==============================================================================
--- portals/jetspeed-2/portal/trunk/pom.xml (original)
+++ portals/jetspeed-2/portal/trunk/pom.xml Wed Apr  1 14:10:20 2009
@@ -811,14 +811,13 @@
         <version>${ehcache.version}</version>
       </dependency>
 
-      <!-- defining dom4j (which is included by commons-configuration) just to be able to exclude
+      <!-- defining dom4j just to be able to exclude
         isorelax, msv and relaxngDatatype
       -->
       <dependency>
         <groupId>dom4j</groupId>
         <artifactId>dom4j</artifactId>
-        <optional>true</optional>
-        <version>[1.4,)</version>
+        <version>1.6.1</version>
         <exclusions>
           <exclusion>
             <groupId>isorelax</groupId>



---------------------------------------------------------------------
To unsubscribe, e-mail: jetspeed-dev-unsubscribe@portals.apache.org
For additional commands, e-mail: jetspeed-dev-help@portals.apache.org