jackrabbit-commits mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From ang...@apache.org
Subject svn commit: r368683 [7/8] - in /incubator/jackrabbit/trunk/contrib/jcr-server: client/ client/src/java/org/apache/jackrabbit/webdav/client/methods/ server/ server/src/java/org/apache/jackrabbit/server/ server/src/java/org/apache/jackrabbit/server/io/ s...
Date Fri, 13 Jan 2006 11:13:30 GMT
Modified: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/OptionsResponse.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/OptionsResponse.java?rev=368683&r1=368682&r2=368683&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/OptionsResponse.java (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/OptionsResponse.java Fri Jan 13 03:11:35 2006
@@ -16,10 +16,19 @@
 package org.apache.jackrabbit.webdav.version;
 
 import org.apache.log4j.Logger;
-import org.apache.jackrabbit.webdav.util.XmlUtil;
-import org.jdom.Document;
-import org.jdom.Element;
-import org.jdom.Namespace;
+import org.apache.jackrabbit.webdav.DavConstants;
+import org.apache.jackrabbit.webdav.xml.XmlSerializable;
+import org.apache.jackrabbit.webdav.xml.Namespace;
+import org.apache.jackrabbit.webdav.xml.DomUtil;
+import org.apache.jackrabbit.webdav.xml.ElementIterator;
+import org.w3c.dom.Element;
+import org.w3c.dom.Document;
+
+import java.util.Map;
+import java.util.HashMap;
+import java.util.Iterator;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * <code>OptionsResponse</code> encapsulates the DAV:options-response element
@@ -31,45 +40,106 @@
  * &lt;!ELEMENT options-response ANY&gt;
  * ANY value: A sequence of elements
  * </pre>
+ *
+ * Please note, that <code>OptionsResponse</code> represents a simplified implementation
+ * of the given structure. We assume, that there may only entries that consist
+ * of a qualified name and a set of href child elements.
+ *
+ * @see DeltaVConstants#XML_ACTIVITY_COLLECTION_SET
+ * @see DeltaVConstants#XML_VH_COLLECTION_SET
+ * @see DeltaVConstants#XML_WSP_COLLECTION_SET
  */
-public class OptionsResponse implements DeltaVConstants {
+public class OptionsResponse implements DeltaVConstants, XmlSerializable {
 
     private static Logger log = Logger.getLogger(OptionsResponse.class);
 
-    private final Element optionsResponse = new Element(XML_OPTIONS_RESPONSE, NAMESPACE);
+    private final Map entries = new HashMap();
 
     /**
-     * Add a new entry to this <code>OptionsResponse</code>
+     * Add a new entry to this <code>OptionsResponse</code> and make each
+     * href present in the String array being a separate {@link org.apache.jackrabbit.webdav.DavConstants#XML_HREF DAV:href}
+     * element within the entry.
      *
-     * @param elem
+     * @param localName
+     * @param namespace
+     * @param hrefs
      */
-    public void addEntry(Element elem) {
-        optionsResponse.addContent(elem.detach());
+    public void addEntry(String localName, Namespace namespace, String[] hrefs) {
+        Entry entry = new Entry(localName, namespace, hrefs);
+        entries.put(DomUtil.getQualifiedName(localName, namespace), entry);
     }
 
     /**
-     * Add a new entry to this <code>OptionsResponse</code> and make each
-     * href present in the String array being a separate {@link org.apache.jackrabbit.webdav.DavConstants#XML_HREF DAV:href}
-     * element within the entry.
      *
-     * @param name
+     * @param localName
      * @param namespace
-     * @param hrefs
+     * @return
      */
-    public void addEntry(String name, Namespace namespace, String[] hrefs) {
-        Element elem = new Element(name, namespace);
-        for (int i = 0; i < hrefs.length; i++) {
-            elem.addContent(XmlUtil.hrefToXml(hrefs[i]));
+    public String[] getHrefs(String localName, Namespace namespace) {
+        String key = DomUtil.getQualifiedName(localName, namespace);
+        if (entries.containsKey(key)) {
+            return ((Entry)entries.get(key)).hrefs;
+        } else {
+            return new String[0];
         }
-        optionsResponse.addContent(elem);
     }
 
     /**
      * Return the Xml representation.
      *
      * @return Xml representation.
+     * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document)
+     * @param document
      */
-    public Document toXml() {
-        return new Document(optionsResponse);
+    public Element toXml(Document document) {
+        Element optionsResponse = DomUtil.createElement(document, XML_OPTIONS_RESPONSE, NAMESPACE);
+        Iterator it = entries.values().iterator();
+        while (it.hasNext()) {
+            Entry entry = (Entry)it.next();
+            Element elem = DomUtil.addChildElement(optionsResponse, entry.localName, entry.namespace);
+            for (int i = 0; i < entry.hrefs.length; i++) {
+                elem.appendChild(DomUtil.hrefToXml(entry.hrefs[i], document));
+            }
+        }
+        return optionsResponse;
+    }
+
+    /**
+     * Build a new <code>OptionsResponse</code> object from the given xml element.
+     *
+     * @param orElem
+     * @return a new <code>OptionsResponse</code> object
+     * @throws IllegalArgumentException if the specified element is <code>null</code>
+     * or if its name is other than 'DAV:options-response'.
+     */
+    public static OptionsResponse createFromXml(Element orElem) {
+        if (!DomUtil.matches(orElem, XML_OPTIONS_RESPONSE, NAMESPACE)) {
+            throw new IllegalArgumentException("DAV:options-response element expected");
+        }
+        OptionsResponse oResponse = new OptionsResponse();
+        ElementIterator it = DomUtil.getChildren(orElem);
+        while (it.hasNext()) {
+            Element el = it.nextElement();
+            List hrefs = new ArrayList();
+            ElementIterator hrefIt = DomUtil.getChildren(el, DavConstants.XML_HREF, DavConstants.NAMESPACE);
+            while (hrefIt.hasNext()) {
+                hrefs.add(DomUtil.getTextTrim(hrefIt.nextElement()));
+            }
+            oResponse.addEntry(el.getLocalName(), DomUtil.getNamespace(el), (String[])hrefs.toArray(new String[hrefs.size()]));
+        }
+        return oResponse;
+    }
+
+    private static class Entry {
+
+        private final String localName;
+        private final Namespace namespace;
+        private final String[] hrefs;
+
+        private Entry(String localName, Namespace namespace, String[] hrefs) {
+            this.localName = localName;
+            this.namespace = namespace;
+            this.hrefs = hrefs;
+        }
     }
 }

Modified: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/SupportedMethodSetProperty.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/SupportedMethodSetProperty.java?rev=368683&r1=368682&r2=368683&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/SupportedMethodSetProperty.java (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/SupportedMethodSetProperty.java Fri Jan 13 03:11:35 2006
@@ -16,30 +16,45 @@
 package org.apache.jackrabbit.webdav.version;
 
 import org.apache.log4j.Logger;
-import org.apache.jackrabbit.webdav.property.DefaultDavProperty;
-import org.jdom.Element;
+import org.apache.jackrabbit.webdav.property.AbstractDavProperty;
+import org.apache.jackrabbit.webdav.xml.DomUtil;
+import org.w3c.dom.Element;
+import org.w3c.dom.Document;
 
 /**
  * The <code>SupportedMethodSetProperty</code>
  */
-public class SupportedMethodSetProperty extends DefaultDavProperty implements DeltaVConstants {
+public class SupportedMethodSetProperty extends AbstractDavProperty implements DeltaVConstants {
 
     private static Logger log = Logger.getLogger(SupportedMethodSetProperty.class);
 
+    private final String[] methods;
+
     /**
      * Create a new <code>SupportedMethodSetProperty</code> property.
      *
      * @param methods that are supported by the resource having this property.
      */
     public SupportedMethodSetProperty(String[] methods) {
-        super(DeltaVConstants.SUPPORTED_METHOD_SET, new Element[methods.length], true);
+        super(DeltaVConstants.SUPPORTED_METHOD_SET, true);
+        this.methods = methods;
+    }
+
+    public Object getValue() {
+        return methods;
+    }
 
-        // fill the array with the proper elements
-        Element[] value = (Element[]) getValue();
+    /**
+     * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document)
+     * @param document
+     */
+    public Element toXml(Document document) {
+        Element elem = getName().toXml(document);
         for (int i = 0; i < methods.length; i++) {
-            Element methodElem = new Element(DeltaVConstants.XML_SUPPORTED_METHOD, DeltaVConstants.NAMESPACE);
-            methodElem.setAttribute("name",methods[i], DeltaVConstants.NAMESPACE);
-            value[i] = methodElem;
+            Element methodElem = DomUtil.addChildElement(elem, XML_SUPPORTED_METHOD, DeltaVConstants.NAMESPACE);
+            DomUtil.setAttribute(methodElem, "name", DeltaVConstants.NAMESPACE, methods[i]);
         }
+        return elem;
     }
+
 }

Modified: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/UpdateInfo.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/UpdateInfo.java?rev=368683&r1=368682&r2=368683&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/UpdateInfo.java (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/UpdateInfo.java Fri Jan 13 03:11:35 2006
@@ -18,10 +18,14 @@
 import org.apache.log4j.Logger;
 import org.apache.jackrabbit.webdav.property.DavPropertyNameSet;
 import org.apache.jackrabbit.webdav.DavConstants;
-import org.jdom.Element;
+import org.apache.jackrabbit.webdav.xml.XmlSerializable;
+import org.apache.jackrabbit.webdav.xml.DomUtil;
+import org.apache.jackrabbit.webdav.xml.ElementIterator;
+import org.w3c.dom.Element;
+import org.w3c.dom.Document;
 
 import java.util.List;
-import java.util.Iterator;
+import java.util.ArrayList;
 
 /**
  * <code>UpdateInfo</code> encapsulates the request body of an UPDATE request.
@@ -45,11 +49,12 @@
  * &lt;!ELEMENT removeExisting EMPTY &gt;
  * </pre>
  */
-public class UpdateInfo implements DeltaVConstants {
+public class UpdateInfo implements DeltaVConstants, XmlSerializable {
 
     private static Logger log = Logger.getLogger(UpdateInfo.class);
 
     private final Element updateElement;
+    private final DavPropertyNameSet propertyNameSet;
     private String[] versionHref;
     private String[] labelName;
     private String workspaceHref;
@@ -63,36 +68,51 @@
      * structure.
      */
     public UpdateInfo(Element updateElement) {
-         if (updateElement == null || !updateElement.getName().equals(DeltaVConstants.XML_UPDATE)) {
+        if (!DomUtil.matches(updateElement, XML_UPDATE, NAMESPACE)) {
             throw new IllegalArgumentException("DAV:update element expected");
         }
 
-        List targetList;
-        if (!(targetList = updateElement.getChildren(XML_VERSION, NAMESPACE)).isEmpty()) {
-            Iterator it = targetList.iterator();
-            versionHref = new String[targetList.size()];
-            int i = 0;
+        boolean done = false;
+        ElementIterator it = DomUtil.getChildren(updateElement, XML_VERSION, NAMESPACE);
             while (it.hasNext()) {
-                Element versionElem = (Element) it.next();
-                versionHref[i] = versionElem.getChildText(DavConstants.XML_HREF, NAMESPACE);
-                i++;
-            }
-        } else if (!(targetList = updateElement.getChildren(XML_LABEL_NAME, NAMESPACE)).isEmpty()) {
-            Iterator it = targetList.iterator();
-            labelName = new String[targetList.size()];
-            int i = 0;
+            List hrefList = new ArrayList();
+            Element el = it.nextElement();
+            hrefList.add(DomUtil.getChildText(el, DavConstants.XML_HREF, DavConstants.NAMESPACE));
+            versionHref = (String[])hrefList.toArray(new String[hrefList.size()]);
+            done = true;
+        }
+
+        // alternatively 'DAV:label-name' elements may be present.
+        if (!done) {
+            it = DomUtil.getChildren(updateElement, XML_LABEL_NAME, NAMESPACE);
             while (it.hasNext()) {
-                Element labelNameElem = (Element) it.next();
-                labelName[i] = labelNameElem.getText();
-                i++;
+                List labelList = new ArrayList();
+                Element el = it.nextElement();
+                labelList.add(DomUtil.getText(el));
+                labelName = (String[])labelList.toArray(new String[labelList.size()]);
+                done = true;
             }
-        } else if (updateElement.getChild(XML_WORKSPACE, NAMESPACE) != null) {
-            workspaceHref = updateElement.getChild(XML_WORKSPACE, NAMESPACE).getChildText(DavConstants.XML_HREF, NAMESPACE);
+        }
+
+        // last possibility: a DAV:workspace element
+        if (!done) {
+            Element wspElem = DomUtil.getChildElement(updateElement, XML_WORKSPACE, NAMESPACE);
+            if (wspElem != null) {
+                workspaceHref = DomUtil.getChildTextTrim(wspElem, DavConstants.XML_HREF, DavConstants.NAMESPACE);
         } else {
             throw new IllegalArgumentException("DAV:update element must contain either DAV:version, DAV:label-name or DAV:workspace child element.");
         }
+        }
 
-        this.updateElement = (Element) updateElement.detach();
+        // if property name set if present
+        if (DomUtil.hasChildElement(updateElement, DavConstants.XML_PROP, DavConstants.NAMESPACE)) {
+            Element propEl = DomUtil.getChildElement(updateElement, DavConstants.XML_PROP, DavConstants.NAMESPACE);
+            propertyNameSet = new DavPropertyNameSet(propEl);
+            updateElement.removeChild(propEl);
+        } else {
+            propertyNameSet = new DavPropertyNameSet();
+        }
+        this.updateElement = updateElement;
     }
 
     /**
@@ -122,18 +142,16 @@
     /**
      * Returns a {@link DavPropertyNameSet}. If the DAV:update element contains
      * a DAV:prop child element the properties specified therein are included
-     * in the set. Otherwise an empty set is returned.
+     * in the set. Otherwise an empty set is returned.<p/>
+     *
+     * <b>WARNING:</b> modifying the DavPropertyNameSet returned by this method does
+     * not modify this <code>UpdateInfo</code>.
      *
      * @return set listing the properties specified in the DAV:prop element indicating
      * those properties that must be reported in the response body.
      */
     public DavPropertyNameSet getPropertyNameSet() {
-        Element propElement = updateElement.getChild(DavConstants.XML_PROP, DavConstants.NAMESPACE);
-        if (propElement != null) {
-            return new DavPropertyNameSet(propElement);
-        } else {
-            return new DavPropertyNameSet();
-        }
+        return propertyNameSet;
     }
 
     /**
@@ -143,4 +161,17 @@
     public Element getUpdateElement() {
         return updateElement;
     }
+
+    /**
+     * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document)
+     * @param document
+     */
+    public Element toXml(Document document) {
+        Element elem = (Element)document.importNode(updateElement, true);
+        if (!propertyNameSet.isEmpty()) {
+            elem.appendChild(propertyNameSet.toXml(document));
+        }
+        return elem;
+    }
+
 }

Modified: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/report/ExpandPropertyReport.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/report/ExpandPropertyReport.java?rev=368683&r1=368682&r2=368683&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/report/ExpandPropertyReport.java (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/report/ExpandPropertyReport.java Fri Jan 13 03:11:35 2006
@@ -15,20 +15,28 @@
  */
 package org.apache.jackrabbit.webdav.version.report;
 
-import org.apache.log4j.Logger;
-import org.apache.jackrabbit.webdav.*;
+import org.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.DavResource;
+import org.apache.jackrabbit.webdav.DavResourceIterator;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.apache.jackrabbit.webdav.MultiStatus;
+import org.apache.jackrabbit.webdav.MultiStatusResponse;
+import org.apache.jackrabbit.webdav.property.AbstractDavProperty;
 import org.apache.jackrabbit.webdav.property.DavProperty;
 import org.apache.jackrabbit.webdav.property.DavPropertyName;
 import org.apache.jackrabbit.webdav.property.HrefProperty;
-import org.apache.jackrabbit.webdav.property.AbstractDavProperty;
 import org.apache.jackrabbit.webdav.version.DeltaVConstants;
 import org.apache.jackrabbit.webdav.version.DeltaVResource;
-import org.jdom.Element;
-import org.jdom.Attribute;
-import org.jdom.Namespace;
-import org.jdom.Document;
+import org.apache.jackrabbit.webdav.xml.DomUtil;
+import org.apache.jackrabbit.webdav.xml.Namespace;
+import org.apache.jackrabbit.webdav.xml.ElementIterator;
+import org.apache.log4j.Logger;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
 
-import java.util.*;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.Iterator;
 
 /**
  * <code>ExpandPropertyReport</code> encapsulates the DAV:expand-property report,
@@ -57,7 +65,7 @@
 
     private DeltaVResource resource;
     private ReportInfo info;
-    private List properties;
+    private Iterator propertyElements;
 
     /**
      * Returns {@link ReportType#EXPAND_PROPERTY}.
@@ -70,15 +78,32 @@
     }
 
     /**
+     * Always returns <code>true</code>.
+     *
+     * @return true
+     * @see org.apache.jackrabbit.webdav.version.report.Report#isMultiStatusReport()
+     */
+    public boolean isMultiStatusReport() {
+        return true;
+    }
+
+    /**
+     * @see Report#init(org.apache.jackrabbit.webdav.version.DeltaVResource, ReportInfo)
+     */
+    public void init(DeltaVResource resource, ReportInfo info) throws DavException {
+        setResource(resource);
+        setInfo(info);
+    }
+
+    /**
      * Set the target resource.
      *
      * @param resource
-     * @throws IllegalArgumentException if the specified resource is <code>null</code>
-     * @see Report#setResource(org.apache.jackrabbit.webdav.version.DeltaVResource)
+     * @throws DavException if the specified resource is <code>null</code>
      */
-    public void setResource(DeltaVResource resource) throws IllegalArgumentException {
+    private void setResource(DeltaVResource resource) throws DavException {
         if (resource == null) {
-            throw new IllegalArgumentException("The resource specified must not be null.");
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST, "The resource specified must not be null.");
         }
         this.resource = resource;
     }
@@ -87,16 +112,15 @@
      * Set the <code>ReportInfo</code>.
      *
      * @param info
-     * @throws IllegalArgumentException if the given <code>ReportInfo</code>
+     * @throws DavException if the given <code>ReportInfo</code>
      * does not contain a DAV:expand-property element.
-     * @see Report#setInfo(ReportInfo)
      */
-    public void setInfo(ReportInfo info) throws IllegalArgumentException {
-        if (info == null || !XML_EXPAND_PROPERTY.equals(info.getReportElement().getName())) {
-            throw new IllegalArgumentException("DAV:expand-property element expected.");
+    private void setInfo(ReportInfo info) throws DavException {
+        if (!getType().isRequestedReportType(info)) {
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:expand-property element expected.");
         }
         this.info = info;
-        properties = info.getReportElement().getChildren(XML_PROPERTY, NAMESPACE);
+        propertyElements = info.getContentElements(XML_PROPERTY, NAMESPACE).iterator();
     }
 
     /**
@@ -104,17 +128,28 @@
      *
      * @return Xml <code>Document</code> as defined by
      * <a href="http://www.ietf.org/rfc/rfc2518.txt">RFC 2518</a>
-     * @throws DavException
-     * @see Report#toXml()
+     * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document)
+     * @param document
+     */
+    public Element toXml(Document document) {
+        return getMultiStatus().toXml(document);
+    }
+
+    /**
+     * Retrieve the multistatus object that is returned in response to the
+     * expand-property report request.
+     *
+     * @return
+     * @throws NullPointerException if info and resource have not been set.
      */
-    public Document toXml() throws DavException {
+    private MultiStatus getMultiStatus() {
         if (info == null || resource == null) {
-            throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, "Error while running DAV:version-tree report");
+            throw new NullPointerException("Error while running DAV:version-tree report");
         }
 
         MultiStatus ms = new MultiStatus();
-        buildMultiStatus(resource, info.getDepth(), ms);
-        return ms.toXml();
+        addResponses(resource, info.getDepth(), ms);
+        return ms;
     }
 
     /**
@@ -125,17 +160,15 @@
      * @param res
      * @param depth
      * @param ms
-     * @throws DavException
-     * @see #getResponse(DavResource, List)
+     * @see #getResponse(DavResource, Iterator)
      */
-    private void buildMultiStatus(DavResource res, int depth, MultiStatus ms)
-            throws DavException {
-        MultiStatusResponse response = getResponse(res, properties);
+    private void addResponses(DavResource res, int depth, MultiStatus ms) {
+        MultiStatusResponse response = getResponse(res, propertyElements);
         ms.addResponse(response);
         if (depth > 0) {
             DavResourceIterator it = res.getMembers();
             while (it.hasNext()) {
-                buildMultiStatus(it.nextResource(), depth-1, ms);
+                addResponses(it.nextResource(), depth-1, ms);
             }
         }
     }
@@ -151,30 +184,31 @@
      * themselves have properties, which are defined by the separate list.
      *
      * @param res
-     * @param propertyList
+     * @param propertyElements
      * @return <code>MultiStatusResponse</code> for the given resource.
      * @see ExpandProperty
      */
-    private MultiStatusResponse getResponse(DavResource res, List propertyList) {
-        MultiStatusResponse resp = new MultiStatusResponse(res.getHref());
-        Iterator propIter = propertyList.iterator();
-        while (propIter.hasNext()) {
-            Element propertyElem = (Element) propIter.next();
-            Attribute nameAttr = propertyElem.getAttribute(ATTR_NAME);
-            if (nameAttr == null) {
+    private MultiStatusResponse getResponse(DavResource res, Iterator propertyElements) {
+        MultiStatusResponse resp = new MultiStatusResponse(res.getHref(), null);
+        while (propertyElements.hasNext()) {
+            Element propertyElem = (Element)propertyElements.next();
+            // retrieve the localName present in the "name" attribute
+            String nameAttr = propertyElem.getAttribute(ATTR_NAME);
+            if (nameAttr == null || "".equals(nameAttr)) {
                 // NOTE: this is not valid according to the DTD
                 continue;
             }
-            Attribute namespaceAttr = propertyElem.getAttribute(ATTR_NAMESPACE);
+            // retrieve the namespace present in the "namespace" attribute
+            // NOTE: if this attribute is missing the DAV: namespace represents the default.
+            String namespaceAttr = propertyElem.getAttribute(ATTR_NAMESPACE);
+            Namespace namespace = (namespaceAttr != null) ? Namespace.getNamespace(namespaceAttr) : NAMESPACE;
 
-            String name = nameAttr.getValue();
-            Namespace namespace = (namespaceAttr != null) ? Namespace.getNamespace(namespaceAttr.getValue()) : NAMESPACE;
-
-            DavPropertyName propName = DavPropertyName.create(name, namespace);
+            DavPropertyName propName = DavPropertyName.create(nameAttr, namespace);
             DavProperty p = res.getProperty(propName);
             if (p != null) {
                 if (p instanceof HrefProperty && res instanceof DeltaVResource) {
-                    resp.add(new ExpandProperty((DeltaVResource)res, (HrefProperty)p, propertyElem.getChildren(XML_PROPERTY, NAMESPACE)));
+                    ElementIterator it = DomUtil.getChildren(propertyElem, XML_PROPERTY, NAMESPACE);
+                    resp.add(new ExpandProperty((DeltaVResource)res, (HrefProperty)p, it));
                 } else {
                     resp.add(p);
                 }
@@ -203,15 +237,15 @@
          * Create a new <code>ExpandProperty</code>.
          *
          * @param hrefProperty
-         * @param propertyList
+         * @param elementIter
          */
-        private ExpandProperty(DeltaVResource deltaVResource, HrefProperty hrefProperty, List propertyList) {
+        private ExpandProperty(DeltaVResource deltaVResource, HrefProperty hrefProperty, ElementIterator elementIter) {
             super(hrefProperty.getName(), hrefProperty.isProtected());
             try {
                 DavResource[] refResource = deltaVResource.getReferenceResources(hrefProperty.getName());
                 for (int i = 0; i < refResource.length; i++) {
-                    MultiStatusResponse resp = getResponse(refResource[i], propertyList);
-                    valueList.add(resp.toXml());
+                    MultiStatusResponse resp = getResponse(refResource[i], elementIter);
+                    valueList.add(resp);
                 }
             } catch (DavException e) {
                 // invalid references or unknown property
@@ -220,7 +254,8 @@
         }
 
         /**
-         * Returns
+         * Returns a List of {@link MultiStatusResponse} objects.
+         *
          * @return
          */
         public Object getValue() {

Modified: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/report/LocateByHistoryReport.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/report/LocateByHistoryReport.java?rev=368683&r1=368682&r2=368683&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/report/LocateByHistoryReport.java (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/report/LocateByHistoryReport.java Fri Jan 13 03:11:35 2006
@@ -15,19 +15,24 @@
  */
 package org.apache.jackrabbit.webdav.version.report;
 
-import org.apache.log4j.Logger;
-import org.apache.jackrabbit.webdav.*;
+import org.apache.jackrabbit.webdav.DavConstants;
+import org.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.DavResource;
+import org.apache.jackrabbit.webdav.DavResourceIterator;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.apache.jackrabbit.webdav.MultiStatus;
 import org.apache.jackrabbit.webdav.property.DavPropertyNameSet;
 import org.apache.jackrabbit.webdav.version.DeltaVConstants;
+import org.apache.jackrabbit.webdav.version.DeltaVResource;
 import org.apache.jackrabbit.webdav.version.VersionControlledResource;
 import org.apache.jackrabbit.webdav.version.VersionHistoryResource;
-import org.apache.jackrabbit.webdav.version.DeltaVResource;
-import org.jdom.Element;
-import org.jdom.Document;
+import org.apache.jackrabbit.webdav.xml.DomUtil;
+import org.apache.jackrabbit.webdav.xml.ElementIterator;
+import org.apache.log4j.Logger;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
 
-import java.util.List;
 import java.util.HashSet;
-import java.util.Iterator;
 
 /**
  * <code>LocateByHistoryReport</code> encapsulates the DAV:locate-by-hisotry
@@ -59,48 +64,49 @@
     }
 
     /**
-     * Set the DeltaVResource.
-     *
-     * @param resource
-     * @throws IllegalArgumentException if the specified resource is not a {@link VersionControlledResource}.
-     * @see Report#setResource(org.apache.jackrabbit.webdav.version.DeltaVResource)
+     * @see Report#init(org.apache.jackrabbit.webdav.version.DeltaVResource, ReportInfo) 
      */
-    public void setResource(DeltaVResource resource) throws IllegalArgumentException {
-        if (resource instanceof VersionControlledResource) {
-            this.resource = resource;
-        } else {
-            throw new IllegalArgumentException("DAV:version-tree report can only be created for version-controlled resources and version resources.");
+    public void init(DeltaVResource resource, ReportInfo info) throws DavException {
+        if (resource == null || !(resource instanceof VersionControlledResource)) {
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:version-tree report can only be created for version-controlled resources and version resources.");
         }
+            this.resource = resource;
+        setInfo(info);
     }
 
     /**
      * Set the <code>ReportInfo</code>
      *
      * @param info
-     * @throws IllegalArgumentException if the given <code>ReportInfo</code>
+     * @throws DavException if the given <code>ReportInfo</code>
      * does not contain a DAV:version-tree element.
-     * @see Report#setInfo(ReportInfo)
      */
-    public void setInfo(ReportInfo info) throws IllegalArgumentException {
-        if (info == null || !XML_LOCATE_BY_HISTORY.equals(info.getReportElement().getName())) {
-            throw new IllegalArgumentException("DAV:locate-by-history element expected.");
+    private void setInfo(ReportInfo info) throws DavException {
+        if (info == null || !getType().isRequestedReportType(info)) {
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:locate-by-history element expected.");
         }
-        Element versionHistorySet = info.getReportElement().getChild(XML_VERSION_HISTORY_SET, NAMESPACE);
+        Element versionHistorySet = info.getContentElement(XML_VERSION_HISTORY_SET, NAMESPACE);
         if (versionHistorySet == null) {
-            throw new IllegalArgumentException("The DAV:locate-by-history element must contain a DAV:version-history-set child.");
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST, "The DAV:locate-by-history element must contain a DAV:version-history-set child.");
         }
-
-        List l = versionHistorySet.getChildren(DavConstants.XML_HREF, DavConstants.NAMESPACE);
-        if (l != null && !l.isEmpty()) {
-            Iterator it = l.iterator();
+        ElementIterator it = DomUtil.getChildren(versionHistorySet, DavConstants.XML_HREF, DavConstants.NAMESPACE);
             while (it.hasNext()) {
-                String href = ((Element)it.next()).getText();
-                if (href != null) {
+            String href = DomUtil.getText(it.nextElement());
+            if (href != null && !"".equals(href)) {
                     vhHrefSet.add(href);
                 }
             }
-        }
         this.info = info;
+        }
+
+    /**
+     * Always returns <code>true</code>.
+     *
+     * @return true
+     * @see org.apache.jackrabbit.webdav.version.report.Report#isMultiStatusReport()
+     */
+    public boolean isMultiStatusReport() {
+        return true;
     }
 
     /**
@@ -108,17 +114,24 @@
      *
      * @return Xml <code>Document</code> representing the report in the required
      * format.
-     * @throws DavException
-     * @see Report#toXml()
+     * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document)
+     * @param document
      */
-    public Document toXml() throws DavException {
-        if (info == null || resource == null) {
-            throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, "Error while running DAV:locate-by-history report");
+    public Element toXml(Document document) {
+        return getMultiStatus().toXml(document);
         }
 
+    /**
+     * Retrieve the <code>MultiStatus</code> that is returned in response to a locate-by-history
+     * report request.
+     *
+     * @return
+     * @throws NullPointerException if info or resource is <code>null</code>.
+     */
+    private MultiStatus getMultiStatus() {
         MultiStatus ms = new MultiStatus();
         buildResponse(resource, info.getPropertyNameSet(), info.getDepth(), ms);
-        return ms.toXml();
+        return ms;
     }
 
     /**
@@ -130,10 +143,9 @@
      * @param propNameSet
      * @param depth
      * @param ms
-     * @throws DavException
      */
     private void buildResponse(DavResource res, DavPropertyNameSet propNameSet,
-                               int depth, MultiStatus ms) throws DavException {
+                               int depth, MultiStatus ms) {
         // loop over members first, since this report only list members
         DavResourceIterator it = res.getMembers();
         while (!vhHrefSet.isEmpty() && it.hasNext()) {

Modified: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/report/Report.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/report/Report.java?rev=368683&r1=368682&r2=368683&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/report/Report.java (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/report/Report.java Fri Jan 13 03:11:35 2006
@@ -15,9 +15,9 @@
  */
 package org.apache.jackrabbit.webdav.version.report;
 
-import org.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.xml.XmlSerializable;
 import org.apache.jackrabbit.webdav.version.DeltaVResource;
-import org.jdom.Document;
+import org.apache.jackrabbit.webdav.DavException;
 
 /**
  * The <code>Report</code> interface defines METHODS needed in order to respond
@@ -26,7 +26,7 @@
  *
  * @see DeltaVResource#getReport(ReportInfo)
  */
-public interface Report {
+public interface Report extends XmlSerializable {
 
     /**
      * Returns the registered type of this report.
@@ -36,29 +36,25 @@
     public ReportType getType();
 
     /**
-     * Set the <code>DeltaVResource</code> for which this report was requested.
-     *
-     * @param resource
-     */
-    public void setResource(DeltaVResource resource);
-
-    /**
-     * Set the <code>ReportInfo</code> as specified by the REPORT request body,
-     * that defines the details for this report.
+     * Returns true if this <code>Report</code> will send a <code>MultiStatus</code>
+     * response.<br>
+     * Please note that RFC 3253 that the the response must be a 207 Multi-Status,
+     * if a Depth request header is present.
      *
-     * @param info providing in detail requirements for this report.
+     * @return
      */
-    public void setInfo(ReportInfo info);
+    public boolean isMultiStatusReport();
 
     /**
-     * Returns the report {@link Document Xml document} defined by the this
-     * <code>ReportType</code>. The document will be returned in the response
-     * body.
+     * Set the <code>DeltaVResource</code> for which this report was requested
+     * and the <code>ReportInfo</code> as specified by the REPORT request body,
+     * that defines the details for this report.<br>
+     * Please note that this methods should perform basic validation checks
+     * in order to prevent execeptional situations during the xml serialization.
      *
-     * @return Xml <code>Document</code> object representing the generated report
-     * in the proper format.
-     * @throws DavException if an error occurs while running the report or
-     * creating the <code>Document</code>.
+     * @param resource
+     * @param info
+     * @throws DavException
      */
-    public Document toXml() throws DavException;
+    public void init(DeltaVResource resource, ReportInfo info) throws DavException;
 }

Modified: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/report/ReportInfo.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/report/ReportInfo.java?rev=368683&r1=368682&r2=368683&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/report/ReportInfo.java (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/report/ReportInfo.java Fri Jan 13 03:11:35 2006
@@ -18,7 +18,17 @@
 import org.apache.log4j.Logger;
 import org.apache.jackrabbit.webdav.property.DavPropertyNameSet;
 import org.apache.jackrabbit.webdav.DavConstants;
-import org.jdom.Element;
+import org.apache.jackrabbit.webdav.xml.XmlSerializable;
+import org.apache.jackrabbit.webdav.xml.DomUtil;
+import org.apache.jackrabbit.webdav.xml.ElementIterator;
+import org.apache.jackrabbit.webdav.xml.Namespace;
+import org.w3c.dom.Element;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+import java.util.Iterator;
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * The <code>ReportInfo</code> class encapsulates the body of a REPORT request.
@@ -26,31 +36,82 @@
  * being the name of the requested report. In addition a Depth header may
  * be present (default value: {@link DavConstants#DEPTH_0}).
  */
-public class ReportInfo {
+public class ReportInfo implements XmlSerializable {
 
     private static Logger log = Logger.getLogger(ReportInfo.class);
 
-    private final Element reportElement;
+    private final String typeLocalName;
+    private final Namespace typeNamespace;
     private final int depth;
+    private final DavPropertyNameSet propertyNames;
+    private final List content = new ArrayList();
 
     /**
-     * Create a new <code>ReportInfo</code> object.
+     * Create a new <code>ReportInfo</code>
      *
-     * @param reportElement
-     * @param depth Depth value as retrieved from the {@link DavConstants#HEADER_DEPTH}.
+     * @param type
      */
-    public ReportInfo(Element reportElement, int depth) {
-        this.reportElement = reportElement;
+    public ReportInfo(ReportType type) {
+        this(type, DavConstants.DEPTH_0, null);
+    }
+
+    /**
+     * Create a new <code>ReportInfo</code>
+     *
+     * @param type
+     * @param depth
+     */
+    public ReportInfo(ReportType type, int depth) {
+        this(type, depth, null);
+    }
+
+    /**
+     * Create a new <code>ReportInfo</code>
+     *
+     * @param type
+     * @param depth
+     * @param propertyNames
+     */
+    public ReportInfo(ReportType type, int depth, DavPropertyNameSet propertyNames) {
+        this.typeLocalName = type.getLocalName();
+        this.typeNamespace = type.getNamespace();
         this.depth = depth;
+        if (propertyNames != null) {
+            this.propertyNames = new DavPropertyNameSet(propertyNames);
+        } else {
+            this.propertyNames = new DavPropertyNameSet();
+        }
     }
 
     /**
-     * Returns the Xml element specifying the requested report.
+     * Create a new <code>ReportInfo</code> object from the given Xml element.
      *
-     * @return reportElement
+     * @param reportElement
+     * @param depth Depth value as retrieved from the {@link DavConstants#HEADER_DEPTH}.
      */
-    public Element getReportElement() {
-        return reportElement;
+    public ReportInfo(Element reportElement, int depth) {
+        if (reportElement == null) {
+            throw new IllegalArgumentException("Report request body must not be null.");
+        }
+
+        this.typeLocalName = reportElement.getLocalName();
+        this.typeNamespace = DomUtil.getNamespace(reportElement);
+        this.depth = depth;
+        Element propElement = DomUtil.getChildElement(reportElement, DavConstants.XML_PROP, DavConstants.NAMESPACE);
+        if (propElement != null) {
+            propertyNames = new DavPropertyNameSet(propElement);
+            reportElement.removeChild(propElement);
+        } else {
+            propertyNames = new DavPropertyNameSet();
+    }
+
+        ElementIterator it = DomUtil.getChildren(reportElement);
+        while (it.hasNext()) {
+            Element el = it.nextElement();
+            if (!DavConstants.XML_PROP.equals(el.getLocalName())) {
+                content.add(el);
+            }
+        }
     }
 
     /**
@@ -65,6 +126,87 @@
     }
 
     /**
+     * Name of the report type that will be / has been requested.
+     *
+     * @return Name of the report type
+     */
+    public String getReportName() {
+        return DomUtil.getQualifiedName(typeLocalName, typeNamespace);
+    }
+
+    /**
+     * Indicates whether this info contains an element with the given name/namespace.
+     *
+     * @param localName
+     * @param namespace
+     * @return true if an element with the given name/namespace is present in the
+     * body of the request info.
+     */
+    public boolean containsContentElement(String localName, Namespace namespace) {
+        if (content.isEmpty()) {
+            return false;
+        }
+        Iterator it = content.iterator();
+        while (it.hasNext()) {
+            Element elem = (Element)it.next();
+            boolean sameNamespace = (namespace == null) ? elem.getNamespaceURI() == null : namespace.isSame(elem.getNamespaceURI());
+            if (sameNamespace && elem.getLocalName().equals(localName)) {
+                return true;
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Retrieves the Xml element with the given name/namespace that is a child
+     * of this info. If no such child exists <code>null</code> is returned. If
+     * multiple elements with the same name exist, the first one is returned.
+     *
+     * @param localName
+     * @param namespace
+     * @return Xml element with the given name/namespace or <code>null</code>
+     */
+    public Element getContentElement(String localName, Namespace namespace) {
+        List values = getContentElements(localName, namespace);
+        if (values.isEmpty()) {
+            return null;
+        } else {
+            return (Element)values.get(0);
+        }
+    }
+
+    /**
+     * Returns a list containing all child Xml elements of this info that have
+     * the specified name/namespace. If this info contains no such element,
+     * an empty list is returned.
+     *
+     * @param localName
+     * @param namespace
+     * @return List contain all child elements with the given name/namespace
+     * or an empty list.
+     */
+    public List getContentElements(String localName, Namespace namespace) {
+        List l = new ArrayList();
+        Iterator it = content.iterator();
+        while (it.hasNext()) {
+            Element elem = (Element)it.next();
+            if (DomUtil.matches(elem, localName, namespace)) {
+                l.add(elem);
+            }
+        }
+        return l;
+    }
+
+    /**
+     * Add the specified Xml element as child of this info.
+     *
+     * @param contentElement
+     */
+    public void setContentElement(Element contentElement) {
+        content.add(contentElement);
+    }
+
+    /**
      * Returns a <code>DavPropertyNameSet</code> providing the property names present
      * in an eventual {@link DavConstants#XML_PROP} child element. If no such
      * child element is present an empty set is returned.
@@ -73,11 +215,31 @@
      * in an eventual {@link DavConstants#XML_PROP DAV:prop} child element or an empty set.
      */
     public DavPropertyNameSet getPropertyNameSet() {
-        Element propElement = reportElement.getChild(DavConstants.XML_PROP, DavConstants.NAMESPACE);
-        if (propElement != null) {
-            return new DavPropertyNameSet(propElement);
-        } else {
-            return new DavPropertyNameSet();
+        return propertyNames;
+    }
+
+
+    /**
+     * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document)
+     * @param document
+     */
+    public Element toXml(Document document) {
+        Element reportElement = DomUtil.createElement(document, typeLocalName, typeNamespace);
+        if (!content.isEmpty()) {
+            Iterator it = content.iterator();
+            while (it.hasNext()) {
+                Object contentEntry = it.next();
+                if (contentEntry instanceof Node) {
+                    Node n = document.importNode((Node)contentEntry, true);
+                    reportElement.appendChild(n);
+                }
+                // else: another object. this should never occure and is therefore ignored.
+            }
+        }
+        if (!propertyNames.isEmpty()) {
+            reportElement.appendChild(propertyNames.toXml(document));
         }
+        return reportElement;
     }
+
 }

Modified: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/report/ReportType.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/report/ReportType.java?rev=368683&r1=368682&r2=368683&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/report/ReportType.java (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/report/ReportType.java Fri Jan 13 03:11:35 2006
@@ -16,19 +16,23 @@
  */
 package org.apache.jackrabbit.webdav.version.report;
 
-import org.apache.log4j.Logger;
-import org.apache.jackrabbit.webdav.version.DeltaVConstants;
 import org.apache.jackrabbit.webdav.DavException;
 import org.apache.jackrabbit.webdav.DavServletResponse;
-import org.jdom.Element;
-import org.jdom.Namespace;
+import org.apache.jackrabbit.webdav.version.DeltaVConstants;
+import org.apache.jackrabbit.webdav.version.DeltaVResource;
+import org.apache.jackrabbit.webdav.xml.DomUtil;
+import org.apache.jackrabbit.webdav.xml.Namespace;
+import org.apache.jackrabbit.webdav.xml.XmlSerializable;
+import org.apache.log4j.Logger;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
 
 import java.util.HashMap;
 
 /**
  * <code>ReportType</code>...
  */
-public class ReportType implements DeltaVConstants {
+public class ReportType implements DeltaVConstants, XmlSerializable {
 
     private static Logger log = Logger.getLogger(ReportType.class);
 
@@ -38,18 +42,20 @@
     public static final ReportType EXPAND_PROPERTY = register(XML_EXPAND_PROPERTY, NAMESPACE, ExpandPropertyReport.class);
     public static final ReportType LOCATE_BY_HISTORY = register(XML_LOCATE_BY_HISTORY, NAMESPACE, LocateByHistoryReport.class);
 
-    private final String name;
+    private final String key;
+    private final String localName;
     private final Namespace namespace;
     private final Class reportClass;
 
     /**
      * Private constructor
      *
-     * @see #register(String, Namespace, Class)
+     * @see ReportType#register(String, org.apache.jackrabbit.webdav.xml.Namespace, Class)
      */
-    private ReportType(String name, Namespace namespace, Class reportClass) {
-        this.name = name;
+    private ReportType(String localName, Namespace namespace, String key, Class reportClass) {
+        this.localName = localName;
         this.namespace = namespace;
+        this.key = key;
         this.reportClass = reportClass;
     }
 
@@ -59,9 +65,11 @@
      * @return
      * @throws DavException
      */
-    public Report createReport() throws DavException {
+    public Report createReport(DeltaVResource resource, ReportInfo info) throws DavException {
         try {
-            return (Report) reportClass.getConstructor(new Class[0]).newInstance(new Object[0]);
+            Report report = (Report) reportClass.getConstructor(new Class[0]).newInstance(new Object[0]);
+            report.init(resource, info);
+            return report;
         } catch (Exception e) {
             // should never occur
             throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, "Failed to register Report.");
@@ -72,10 +80,12 @@
      * Returns an Xml element representing this report type. It may be used to
      * build the body for a REPORT request.
      *
+     * @param document
      * @return Xml representation
+     * @see XmlSerializable#toXml(org.w3c.dom.Document)
      */
-    public Element toXml() {
-        return new Element(name, namespace);
+    public Element toXml(Document document) {
+        return DomUtil.createElement(document, localName, namespace);
     }
 
     /**
@@ -87,19 +97,41 @@
      */
     public boolean isRequestedReportType(ReportInfo reqInfo) {
         if (reqInfo != null) {
-            Element elem = reqInfo.getReportElement();
-            if (elem != null) {
-                return name.equals(elem.getName()) && namespace.equals(elem.getNamespace());
-            }
+            return getReportName().equals(reqInfo.getReportName());
         }
         return false;
     }
 
     /**
+     * Return the qualified name of this <code>ReportType</code>.
+     *
+     * @return qualified name
+     */
+    public String getReportName() {
+        return key;
+            }
+
+    /**
+     *
+     * @return
+     */
+    public String getLocalName() {
+        return localName;
+        }
+
+    /**
+     *
+     * @return
+     */
+    public Namespace getNamespace() {
+        return namespace;
+    }
+
+    /**
      * Register the report type with the given name, namespace and class, that can
      * run that report.
      *
-     * @param name
+     * @param localName
      * @param namespace
      * @param reportClass
      * @return
@@ -107,12 +139,12 @@
      * if the given class does not implement the {@link Report} interface or if
      * it does not provide an empty constructor.
      */
-    public static ReportType register(String name, Namespace namespace, Class reportClass) {
-        if (name == null || namespace == null || reportClass == null) {
+    public static ReportType register(String localName, Namespace namespace, Class reportClass) {
+        if (localName == null || namespace == null || reportClass == null) {
             throw new IllegalArgumentException("A ReportType cannot be registered with a null name, namespace or report class");
         }
 
-        String key = buildKey(namespace, name);
+        String key = DomUtil.getQualifiedName(localName, namespace);
         if (types.containsKey(key)) {
             return (ReportType) types.get(key);
         } else {
@@ -132,7 +164,7 @@
                 throw new IllegalArgumentException("The specified report class must provide a default constructor.");
             }
 
-            ReportType type = new ReportType(name, namespace, reportClass);
+            ReportType type = new ReportType(localName, namespace, key, reportClass);
             types.put(key, type);
             return type;
         }
@@ -150,22 +182,11 @@
         if (reportInfo == null) {
             throw new IllegalArgumentException("ReportInfo must not be null.");
         }
-        String key = buildKey(reportInfo.getReportElement().getNamespace(), reportInfo.getReportElement().getName());
+        String key = reportInfo.getReportName();
         if (types.containsKey(key)) {
             return (ReportType) types.get(key);
         } else {
             throw new IllegalArgumentException("The request report '"+key+"' has not been registered yet.");
         }
-    }
-
-    /**
-     * Build the key from the given namespace and name.
-     *
-     * @param namespace
-     * @param name
-     * @return key identifying the report with the given namespace and name
-     */
-    private static String buildKey(Namespace namespace, String name) {
-        return "{" + namespace.getURI() + "}" + name;
     }
 }

Modified: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/report/SupportedReportSetProperty.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/report/SupportedReportSetProperty.java?rev=368683&r1=368682&r2=368683&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/report/SupportedReportSetProperty.java (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/report/SupportedReportSetProperty.java Fri Jan 13 03:11:35 2006
@@ -18,7 +18,9 @@
 import org.apache.log4j.Logger;
 import org.apache.jackrabbit.webdav.version.DeltaVConstants;
 import org.apache.jackrabbit.webdav.property.AbstractDavProperty;
-import org.jdom.Element;
+import org.apache.jackrabbit.webdav.xml.DomUtil;
+import org.w3c.dom.Element;
+import org.w3c.dom.Document;
 
 import java.util.HashSet;
 import java.util.Iterator;
@@ -87,29 +89,31 @@
     }
 
     /**
+     * Returns a set of report types.
+     *
+     * @return set of {@link ReportType}.
+     * @see org.apache.jackrabbit.webdav.property.DavProperty#getValue()
+     */
+    public Object getValue() {
+        return reportTypes;
+    }
+
+    /**
      * Returns the Xml representation of this property.
      *
      * @return Xml representation listing all supported reports
-     * @see org.apache.jackrabbit.webdav.property.DavProperty#toXml()
+     * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document)
+     * @param document
      */
-    public Element toXml() {
-        Element elem = getName().toXml();
+    public Element toXml(Document document) {
+        Element elem = getName().toXml(document);
         Iterator it = reportTypes.iterator();
         while (it.hasNext()) {
-	    Element sr = new Element(DeltaVConstants.XML_SUPPORTED_REPORT, DeltaVConstants.NAMESPACE);
-            Element r = new Element(DeltaVConstants.XML_REPORT, DeltaVConstants.NAMESPACE);
-	    elem.addContent(sr.addContent(r.addContent(((ReportType)it.next()).toXml())));
+	    Element sr = DomUtil.addChildElement(elem, DeltaVConstants.XML_SUPPORTED_REPORT, DeltaVConstants.NAMESPACE);
+            Element r = DomUtil.addChildElement(sr, DeltaVConstants.XML_REPORT, DeltaVConstants.NAMESPACE);
+	    r.appendChild(((ReportType)it.next()).toXml(document));
         }
         return elem;
     }
 
-    /**
-     * Returns a set of report types.
-     *
-     * @return set of {@link ReportType}.
-     * @see org.apache.jackrabbit.webdav.property.DavProperty#getValue()
-     */
-    public Object getValue() {
-        return reportTypes;
-    }
 }

Modified: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/report/VersionTreeReport.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/report/VersionTreeReport.java?rev=368683&r1=368682&r2=368683&view=diff
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/report/VersionTreeReport.java (original)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/version/report/VersionTreeReport.java Fri Jan 13 03:11:35 2006
@@ -16,10 +16,18 @@
 package org.apache.jackrabbit.webdav.version.report;
 
 import org.apache.log4j.Logger;
-import org.apache.jackrabbit.webdav.*;
 import org.apache.jackrabbit.webdav.property.DavPropertyNameSet;
-import org.apache.jackrabbit.webdav.version.*;
-import org.jdom.Document;
+import org.apache.jackrabbit.webdav.version.DeltaVConstants;
+import org.apache.jackrabbit.webdav.version.DeltaVResource;
+import org.apache.jackrabbit.webdav.version.VersionControlledResource;
+import org.apache.jackrabbit.webdav.version.VersionResource;
+import org.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.apache.jackrabbit.webdav.MultiStatus;
+import org.apache.jackrabbit.webdav.DavResource;
+import org.apache.jackrabbit.webdav.DavResourceIterator;
+import org.w3c.dom.Element;
+import org.w3c.dom.Document;
 
 /**
  * <code>VersionTreeReport</code> encapsulates the DAV:version-tree report.
@@ -34,23 +42,51 @@
     private ReportInfo info;
     private DeltaVResource resource;
 
+    /**
+     * Returns {@link ReportType#VERSION_TREE}
+     *
+     * @return {@link ReportType#VERSION_TREE}
+     * @see Report#getType()
+     */
     public ReportType getType() {
         return ReportType.VERSION_TREE;
     }
 
     /**
+     * Always returns <code>true</code>.
+     *
+     * @return true
+     * @see org.apache.jackrabbit.webdav.version.report.Report#isMultiStatusReport()
+     */
+    public boolean isMultiStatusReport() {
+        return true;
+    }
+
+    /**
+     * Validates the specified resource and info objects.
+     *
+     * @param resource
+     * @param info
+     * @throws org.apache.jackrabbit.webdav.DavException
+     * @see Report#init(org.apache.jackrabbit.webdav.version.DeltaVResource, ReportInfo)
+     */
+    public void init(DeltaVResource resource, ReportInfo info) throws DavException {
+        setResource(resource);
+        setInfo(info);
+    }
+
+    /**
      * Set the <code>DeltaVResource</code> used to register this report.
      *
      * @param resource
-     * @throws IllegalArgumentException if the given resource is neither
-     * {@link VersionControlledResource} nor {@link VersionResource}.
-     * @see Report#setResource(org.apache.jackrabbit.webdav.version.DeltaVResource)
+     * @throws DavException if the given resource is neither
+     * {@link org.apache.jackrabbit.webdav.version.VersionControlledResource} nor {@link org.apache.jackrabbit.webdav.version.VersionResource}.
      */
-    public void setResource(DeltaVResource resource) throws IllegalArgumentException {
-        if (resource instanceof VersionControlledResource || resource instanceof VersionResource) {
+    private void setResource(DeltaVResource resource) throws DavException {
+        if (resource != null && (resource instanceof VersionControlledResource || resource instanceof VersionResource)) {
             this.resource = resource;
         } else {
-            throw new IllegalArgumentException("DAV:version-tree report can only be created for version-controlled resources and version resources.");
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:version-tree report can only be created for version-controlled resources and version resources.");
         }
     }
 
@@ -59,13 +95,12 @@
      * that defines the details for this report.
      *
      * @param info
-     * @throws IllegalArgumentException if the given <code>ReportInfo</code>
+     * @throws DavException if the given <code>ReportInfo</code>
      * does not contain a DAV:version-tree element.
-     * @see Report#setInfo(ReportInfo)
      */
-    public void setInfo(ReportInfo info) throws IllegalArgumentException {
-        if (info == null || !XML_VERSION_TREE.equals(info.getReportElement().getName())) {
-            throw new IllegalArgumentException("DAV:version-tree element expected.");
+    private void setInfo(ReportInfo info) throws DavException {
+        if (!getType().isRequestedReportType(info)) {
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST, "DAV:version-tree element expected.");
         }
         this.info = info;
     }
@@ -75,18 +110,28 @@
      *
      * @return Xml <code>Document</code> representing the report in the required
      * format.
-     * @throws DavException if the resource or the info field are <code>null</code>
-     * or if any other error occurs.
-     * @see Report#toXml()
+     * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(Document)
+     * @param document
+     */
+    public Element toXml(Document document) {
+        return getMultiStatus().toXml(document);
+    }
+
+    /**
+     * Retrieve the <code>MultiStatus</code> that is returned in response to a locate-by-history
+     * report request.
+     *
+     * @return
+     * @throws NullPointerException if info or resource is <code>null</code>.
      */
-    public Document toXml() throws DavException {
+    private MultiStatus getMultiStatus() {
         if (info == null || resource == null) {
-            throw new DavException(DavServletResponse.SC_INTERNAL_SERVER_ERROR, "Error while running DAV:version-tree report");
+            throw new NullPointerException("Error while running DAV:version-tree report");
         }
 
         MultiStatus ms = new MultiStatus();
         buildResponse(resource, info.getPropertyNameSet(), info.getDepth(), ms);
-        return ms.toXml();
+        return ms;
     }
 
     /**
@@ -95,10 +140,10 @@
      * @param propNameSet
      * @param depth
      * @param ms
-     * @throws DavException
      */
     private void buildResponse(DavResource res, DavPropertyNameSet propNameSet,
-                               int depth, MultiStatus ms) throws DavException {
+                               int depth, MultiStatus ms) {
+        try {
         VersionResource[] versions = getVersions(res);
         for (int i = 0; i < versions.length; i++) {
             if (propNameSet.isEmpty()) {
@@ -106,6 +151,9 @@
             } else {
                 ms.addResourceProperties(versions[i], propNameSet, 0);
             }
+            }
+        } catch (DavException e) {
+            log.error(e);
         }
         if (depth > 0) {
             DavResourceIterator it = res.getMembers();

Added: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/xml/DomUtil.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/xml/DomUtil.java?rev=368683&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/xml/DomUtil.java (added)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/xml/DomUtil.java Fri Jan 13 03:11:35 2006
@@ -0,0 +1,547 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed 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.jackrabbit.webdav.xml;
+
+import org.apache.log4j.Logger;
+import org.apache.jackrabbit.webdav.DavConstants;
+import org.w3c.dom.Attr;
+import org.w3c.dom.CharacterData;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Text;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * <code>DomUtil</code> provides some common utility methods related to w3c-DOM.
+ */
+public class DomUtil {
+
+    private static Logger log = Logger.getLogger(DomUtil.class);
+
+    /**
+     * Returns the value of the named attribute of the current element.
+     *
+     * @param parent
+     * @param localName attribute local name or 'nodeName' if no namespace is
+     * specified.
+     * @param  namespace or <code>null</code>
+     * @return attribute value, or <code>null</code> if not found
+     */
+    public static String getAttribute(Element parent, String localName, Namespace namespace) {
+        if (parent == null) {
+            return null;
+        }
+        Attr attribute;
+        if (namespace == null) {
+            attribute = parent.getAttributeNode(localName);
+        } else {
+            attribute = parent.getAttributeNodeNS(namespace.getURI(), localName);
+        }
+        if (attribute != null) {
+            return attribute.getValue();
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * Concatenates the values of all child nodes of type 'Text' or 'CDATA'/
+     *
+     * @param element
+     * @return String representing the value of all Text and CDATA child nodes or
+     * <code>null</code> if the length of the resulting String is 0.
+     * @see #isText(Node)
+     */
+    public static String getText(Element element) {
+        StringBuffer content = new StringBuffer();
+        if (element != null) {
+            NodeList nodes = element.getChildNodes();
+            for (int i = 0; i < nodes.getLength(); i++) {
+                Node child = nodes.item(i);
+                if (isText(child)) {
+                    // cast to super class that contains Text and CData
+                    content.append(((CharacterData) child).getData());
+                }
+            }
+        }
+        return (content.length()==0) ? null : content.toString();
+    }
+
+    /**
+     * Removes leading and trailing whitespace after calling {@link #getText(Element).
+     *
+     * @param element
+     * @return Trimmed text or <code>null</code>
+     */
+    public static String getTextTrim(Element element) {
+        String txt = getText(element);
+        return (txt == null) ? txt : txt.trim();
+    }
+
+    /**
+     * Calls {@link #getText(Element)} on the first child element that matches
+     * the given local name and namespace.
+     *
+     * @param parent
+     * @param childLocalName
+     * @param childNamespace
+     * @return text contained in the first child that matches the given local name
+     * and namespace or <code>null</code>.
+     * @see #getText(Element)
+     */
+    public static String getChildText(Element parent, String childLocalName, Namespace childNamespace) {
+        Element child = getChildElement(parent, childLocalName, childNamespace);
+        return (child == null) ? null : getText(child);
+    }
+
+    /**
+     * Calls {@link #getTextTrim(Element)} on the first child element that matches
+     * the given local name and namespace.
+     *
+     * @param parent
+     * @param childLocalName
+     * @param childNamespace
+     * @return text contained in the first child that matches the given local name
+     * and namespace or <code>null</code>. Note, that leading and trailing whitespace
+     * is removed from the text.
+     * @see #getTextTrim(Element)
+     */
+    public static String getChildTextTrim(Element parent, String childLocalName, Namespace childNamespace) {
+        Element child = getChildElement(parent, childLocalName, childNamespace);
+        return (child == null) ? null : getTextTrim(child);
+    }
+
+    /**
+     * Returns true if the given parent node has a child element that matches
+     * the specified local name and namespace.
+     *
+     * @param parent
+     * @param childLocalName
+     * @param childNamespace
+     * @return returns true if  a child element exists that matches the specified
+     * local name and namespace.
+     */
+    public static boolean hasChildElement(Node parent, String childLocalName, Namespace childNamespace) {
+        return getChildElement(parent, childLocalName, childNamespace) != null;
+    }
+
+    /**
+     * Returns the first child element that matches the given local name and
+     * namespace. If no child element is present or no child element matches,
+     * <code>null</code> is returned.
+     *
+     * @param parent
+     * @param childLocalName
+     * @param childNamespace
+     * @return first child element matching the specified names or <code>null</code>.
+     */
+    public static Element getChildElement(Node parent, String childLocalName, Namespace childNamespace) {
+        if (parent != null) {
+            NodeList children = parent.getChildNodes();
+            for (int i = 0; i < children.getLength(); i++) {
+                Node child = children.item(i);
+                if (isElement(child) && matches(child, childLocalName, childNamespace)) {
+                    return (Element)child;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Returns a <code>ElementIterator</code> containing all child elements of
+     * the given parent node that match the given local name and namespace.
+     * If the namespace is <code>null</code> only the localName is compared.
+     *
+     * @param parent the node the children elements should be retrieved from
+     * @param childLocalName
+     * @param childNamespace
+     * @return an <code>ElementIterator</code> giving access to all child elements
+     * that match the specified localName and namespace.
+     */
+    public static ElementIterator getChildren(Element parent, String childLocalName, Namespace childNamespace) {
+        return new ElementIterator(parent, childLocalName, childNamespace);
+    }
+
+    /**
+     * Return an <code>ElementIterator</code> over all child elements.
+     *
+     * @param parent
+     * @return
+     * @see #getChildren(Element, String, Namespace) for a method that only
+     * retrieves child elements that match a specific local name and namespace.
+     */
+    public static ElementIterator getChildren(Element parent) {
+        return new ElementIterator(parent);
+    }
+
+    /**
+     * Return the first child element
+     *
+     * @return the first child element or <code>null</code> if the given node has no
+     * child elements.
+     */
+    public static Element getFirstChildElement(Node parent) {
+        if (parent != null) {
+            NodeList children = parent.getChildNodes();
+            for (int i = 0; i < children.getLength(); i++) {
+                Node child = children.item(i);
+                if (isElement(child)) {
+                    return (Element)child;
+                }
+            }
+        }
+        return null;
+    }
+
+    /**
+     * Return true if the given parent contains any child that is either an
+     * Element, Text or CDATA.
+     *
+     * @param parent
+     * @return
+     */
+    public static boolean hasContent(Node parent) {
+        if (parent != null) {
+            NodeList children = parent.getChildNodes();
+            for (int i = 0; i < children.getLength(); i++) {
+                Node child = children.item(i);
+                if (isAcceptedNode(child)) {
+                    return true;
+                }
+            }
+        }
+        return false;
+    }
+
+    /**
+     * Return a list of all child nodes that are either Element, Text or CDATA.
+     *
+     * @param parent
+     * @return
+     */
+    public static List getContent(Node parent) {
+        List content = new ArrayList();
+        if (parent != null) {
+            NodeList children = parent.getChildNodes();
+            for (int i = 0; i < children.getLength(); i++) {
+                Node child = children.item(i);
+                if (isAcceptedNode(child)) {
+                    content.add(child);
+                }
+            }
+        }
+        return content;
+    }
+
+    /**
+     * Build a Namespace from the prefix and uri retrieved from the given element.
+     *
+     * @return
+     */
+    public static Namespace getNamespace(Element element) {
+        String uri = element.getNamespaceURI();
+        String prefix = element.getPrefix();
+        if (uri == null) {
+            return Namespace.EMPTY_NAMESPACE;
+        } else {
+            return Namespace.getNamespace(prefix, uri);
+        }
+    }
+
+    /**
+     * Returns true if the specified node matches the required names. Note, that
+     * that tests return true if the required name is <code>null</code>.
+     *
+     * @param node
+     * @param requiredLocalName
+     * @param requiredNamespace
+     * @return true if local name and namespace match the corresponding properties
+     * of the given DOM node.
+     */
+    public static boolean matches(Node node, String requiredLocalName, Namespace requiredNamespace) {
+        if (node == null) {
+            return false;
+        }
+        boolean matchingNamespace = matchingNamespace(node, requiredNamespace);
+        return matchingNamespace && matchingLocalName(node, requiredLocalName);
+    }
+
+    /**
+     * @param node
+     * @param requiredNamespace
+     * @return true if the required namespace is <code>null</code> or matches
+     * the namespace of the specified node.
+     */
+    private static boolean matchingNamespace(Node node, Namespace requiredNamespace) {
+        if (requiredNamespace == null) {
+            return true;
+        } else {
+            return requiredNamespace.isSame(node.getNamespaceURI());
+        }
+    }
+
+    /**
+     * @param node
+     * @param requiredLocalName
+     * @return true if the required local name is <code>null</code> or if the
+     * nodes local name matches.
+     */
+    private static boolean matchingLocalName(Node node, String requiredLocalName) {
+        if (requiredLocalName == null) {
+            return true;
+        } else {
+            String localName = node.getLocalName();
+            return requiredLocalName.equals(localName);
+        }
+    }
+
+    /**
+     * @param node
+     * @return true if the specified node is either an element or Text or CDATA
+     */
+    private static boolean isAcceptedNode(Node node) {
+        return isElement(node) || isText(node);
+    }
+
+    /**
+     * @param node
+     * @return true if the given node is of type element.
+     */
+    static boolean isElement(Node node) {
+        return node.getNodeType() == Node.ELEMENT_NODE;
+    }
+
+    /**
+     * @param node
+     * @return true if the given node is of type text or CDATA.
+     */
+    static boolean isText(Node node) {
+        int ntype = node.getNodeType();
+        return ntype == Node.TEXT_NODE || ntype == Node.CDATA_SECTION_NODE;
+    }
+
+    //----------------------------------------------------< factory methods >---
+    /**
+     * Create a new DOM element with the specified local name and namespace.
+     *
+     * @param factory
+     * @param localName
+     * @param namespace
+     * @return a new DOM element
+     * @see Document#createElement(String)
+     * @see Document#createElementNS(String, String)
+     */
+    public static Element createElement(Document factory, String localName, Namespace namespace) {
+        if (namespace != null) {
+            return factory.createElementNS(namespace.getURI(), getPrefixedName(localName, namespace));
+        } else {
+            return factory.createElement(localName);
+        }
+    }
+
+    /**
+     * Create a new DOM element with the specified local name and namespace and
+     * add the specified text as Text node to it.
+     *
+     * @param factory
+     * @param localName
+     * @param namespace
+     * @param text
+     * @return a new DOM element
+     * @see Document#createElement(String)
+     * @see Document#createElementNS(String, String)
+     * @see Document#createTextNode(String)
+     * @see Node#appendChild(org.w3c.dom.Node)
+     */
+    public static Element createElement(Document factory, String localName, Namespace namespace, String text) {
+        Element elem = createElement(factory, localName, namespace);
+        setText(elem, text);
+        return elem;
+    }
+
+    /**
+     * Add a new child element with the given local name and namespace to the
+     * specified parent.
+     *
+     * @param parent
+     * @param localName
+     * @param namespace
+     * @return the new element that was attached to the given parent.
+     */
+    public static Element addChildElement(Element parent, String localName, Namespace namespace) {
+        Element elem = createElement(parent.getOwnerDocument(), localName, namespace);
+        parent.appendChild(elem);
+        return elem;
+    }
+
+    /**
+     * Add a new child element with the given local name and namespace to the
+     * specified parent. The specified text is added as Text node to the created
+     * child element.
+     *
+     * @param parent
+     * @param localName
+     * @param namespace
+     * @param text
+     * @return child element that was added to the specified parent
+     * @see Document#createElement(String)
+     * @see Document#createElementNS(String, String)
+     * @see Document#createTextNode(String)
+     * @see Node#appendChild(org.w3c.dom.Node)
+     */
+    public static Element addChildElement(Element parent, String localName, Namespace namespace, String text) {
+        Element elem = createElement(parent.getOwnerDocument(), localName, namespace, text);
+        parent.appendChild(elem);
+        return elem;
+    }
+
+    /**
+     * Create a new text node and add it as child to the given element.
+     *
+     * @param element
+     * @param text
+     */
+    public static void setText(Element element, String text) {
+        if (text == null || "".equals(text)) {
+            // ignore null/empty string text
+            return;
+        }
+        Text txt = element.getOwnerDocument().createTextNode(text);
+        element.appendChild(txt);
+    }
+
+    /**
+     * Add an attribute node to the given element.
+     *
+     * @param element
+     * @param attrLocalName
+     * @param attrNamespace
+     * @param attrValue
+     */
+    public static void setAttribute(Element element, String attrLocalName, Namespace attrNamespace, String attrValue) {
+        if (attrNamespace == null) {
+            Attr attr = element.getOwnerDocument().createAttribute(attrLocalName);
+            attr.setValue(attrValue);
+            element.setAttributeNode(attr);
+        } else {
+            Attr attr = element.getOwnerDocument().createAttributeNS(attrNamespace.getURI(), getPrefixedName(attrLocalName, attrNamespace));
+            attr.setValue(attrValue);
+            element.setAttributeNodeNS(attr);
+        }
+    }
+
+    /**
+     * Converts the given timeout (long value defining the number of milli-
+     * second until timeout is reached) to its Xml representation as defined
+     * by RTF 2518.<br>
+     * Note, that {@link DavConstants#INFINITE_TIMEOUT} is not represented by the String
+     * {@link DavConstants#TIMEOUT_INFINITE 'Infinite'} defined by RFC 2518, due to a known
+     * issue with Microsoft Office that opens the document "read only" and
+     * never unlocks the resource if the timeout is missing or 'Infinite'.
+     *
+     * @param timeout number of milli-seconds until timeout is reached.
+     * @return 'timeout' Xml element
+     */
+    public static Element timeoutToXml(long timeout, Document factory) {
+        String expString = "Second-"+ timeout/1000;;
+        Element exp = createElement(factory, DavConstants.XML_TIMEOUT, DavConstants.NAMESPACE, expString);
+        return exp;
+    }
+
+    /**
+     * Returns the Xml representation of a boolean isDeep, where false
+     * presents a depth value of '0', true a depth value of 'infinity'.
+     *
+     * @param isDeep
+     * @return Xml representation
+     */
+    public static Element depthToXml(boolean isDeep, Document factory) {
+        return depthToXml(isDeep? "infinity" : "0", factory);
+    }
+
+    /**
+     * Returns the Xml representation of a depth String. Webdav defines the
+     * following valid values for depths: 0, 1, infinity
+     *
+     * @param depth
+     * @return 'deep' JDOM element
+     */
+    public static Element depthToXml(String depth, Document factory) {
+        Element dElem = createElement(factory, DavConstants.XML_DEPTH, DavConstants.NAMESPACE, depth);
+        return dElem;
+    }
+
+    /**
+     * Builds a 'DAV:href' Xml element from the given href. Please note, that
+     * the path present in the given String should be properly
+     * {@link org.apache.jackrabbit.util.Text#escapePath(String) escaped} in order to prevent problems with
+     * WebDAV clients.
+     *
+     * @param href String representing the text of the 'href' Xml element
+     * @param factory the Document used as factory
+     * @return Xml representation of a 'href' according to RFC 2518.
+     */
+    public static Element hrefToXml(String href, Document factory) {
+        return createElement(factory, DavConstants.XML_HREF, DavConstants.NAMESPACE, href);
+    }
+
+    /**
+     * Return a qualified name of a DOM node consisting of "{" + namespace uri + "}"
+     * + localName. If the specified namespace is <code>null</code> or represents
+     * the empty namespace, the local name is returned.
+     *
+     * @param localName
+     * @param namespace
+     * @return
+     */
+    public static String getQualifiedName(String localName, Namespace namespace) {
+        if (namespace == null || namespace.equals(Namespace.EMPTY_NAMESPACE)) {
+            return localName;
+        }
+        StringBuffer b = new StringBuffer("{");
+        b.append(namespace.getURI()).append("}");
+        b.append(localName);
+        return b.toString();
+    }
+
+    /**
+     * Return the prefixed name of a DOM node consisting of
+     * namespace prefix + ":" + local name. If the specified namespace is <code>null</code>
+     * or contains an empty prefix, the local name is returned.<br>
+     * NOTE, that this is the value to be used for the 'qualified Name' parameter
+     * expected with the namespace sensitive factory methods.
+     *
+     * @param localName
+     * @param namespace
+     * @return qualified name consisting of prefix, ':' and local name.
+     * @see Document#createAttributeNS(String, String)
+     * @see Document#createElementNS(String, String)
+     */
+    public static String getPrefixedName(String localName, Namespace namespace) {
+        if (namespace == null || namespace.equals(Namespace.EMPTY_NAMESPACE) || "".equals(namespace.getPrefix())) {
+            return localName;
+        }
+        StringBuffer buf = new StringBuffer(namespace.getPrefix());
+        buf.append(":");
+        buf.append(localName);
+        return buf.toString();
+    }
+}
\ No newline at end of file

Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/xml/DomUtil.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/xml/DomUtil.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url

Added: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/xml/ElementIterator.java
URL: http://svn.apache.org/viewcvs/incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/xml/ElementIterator.java?rev=368683&view=auto
==============================================================================
--- incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/xml/ElementIterator.java (added)
+++ incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/xml/ElementIterator.java Fri Jan 13 03:11:35 2006
@@ -0,0 +1,135 @@
+/*
+ * Copyright 2005 The Apache Software Foundation.
+ *
+ * Licensed 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.jackrabbit.webdav.xml;
+
+import org.apache.log4j.Logger;
+import org.w3c.dom.Element;
+import org.w3c.dom.NodeList;
+import org.w3c.dom.Node;
+
+import java.util.Iterator;
+import java.util.NoSuchElementException;
+
+/**
+ * <code>ElementIterator</code>...
+ */
+public class ElementIterator implements Iterator {
+
+    private static Logger log = Logger.getLogger(ElementIterator.class);
+
+    private final Namespace namespace;
+    private final String localName;
+
+    private Element next;
+
+    /**
+     * Create a new instance of <code>ElementIterator</code> with the given
+     * parent element. Only child elements that match the given local name
+     * and namespace will be respected by {@link #hasNext()} and {@link #nextElement()}.
+     *
+     * @param parent
+     * @param localName local name the child elements must match
+     * @param namespace namespace the child elements must match
+     */
+    public ElementIterator(Element parent, String localName, Namespace namespace) {
+        this.localName = localName;
+        this.namespace = namespace;
+        seek(parent);
+    }
+
+    /**
+     * Create a new instance of <code>ElementIterator</code> with the given
+     * parent element. No filtering is applied to child elements that are
+     * iterated.
+     *
+     * @param parent
+     */
+    public ElementIterator(Element parent) {
+        this(parent, null, null);
+    }
+
+    /**
+     * Not implemented
+     *
+     * @throws UnsupportedOperationException
+     */
+    public void remove() {
+        throw new UnsupportedOperationException("Remove not implemented.");
+    }
+
+    /**
+     * Returns true if there is a next <code>Element</code>
+     *
+     * @return true if a next <code>Element</code> is available.
+     */
+    public boolean hasNext() {
+        return next != null;
+    }
+
+    /**
+     * @see java.util.Iterator#next()
+     * @see #nextElement()
+     */
+    public Object next() {
+        return nextElement();
+    }
+
+    /**
+     * Returns the next <code>Element</code> in the iterator.
+     *
+     * @return the next element
+     * @throws NoSuchElementException if there is no next element.
+     */
+    public Element nextElement() {
+        if (next==null) {
+            throw new NoSuchElementException();
+        }
+        Element ret = next;
+        seek();
+        return ret;
+    }
+
+    /**
+     * Seeks for the first matching child element
+     */
+    private void seek(Element parent) {
+        NodeList nodeList = parent.getChildNodes();
+        for (int i = 0; i < nodeList.getLength(); i++) {
+            Node n = nodeList.item(i);
+            if (DomUtil.isElement(n) && DomUtil.matches(n, localName, namespace)) {
+                next = (Element)n;
+                return;
+            }
+        }
+    }
+
+    /**
+     * Seeks for the next valid element (i.e. the next valid sibling)
+     */
+    private void seek() {
+        Node n = next.getNextSibling();
+        while (n != null) {
+            if (DomUtil.isElement(n) && DomUtil.matches(n, localName, namespace)) {
+                next = (Element)n;
+                return;
+            } else {
+                n = n.getNextSibling();
+            }
+        }
+        // no next element found -> set to null in order to leave the loop.
+        next = null;
+    }
+}
\ No newline at end of file

Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/xml/ElementIterator.java
------------------------------------------------------------------------------
    svn:eol-style = native

Propchange: incubator/jackrabbit/trunk/contrib/jcr-server/webdav/src/java/org/apache/jackrabbit/webdav/xml/ElementIterator.java
------------------------------------------------------------------------------
    svn:keywords = author date id revision url



Mime
View raw message