You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@jackrabbit.apache.org by re...@apache.org on 2008/09/29 14:32:29 UTC

svn commit: r700097 [1/2] - in /jackrabbit/trunk: jackrabbit-jcr-server/ jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/ jackrabbit-webapp/src/main/webapp/ jackrabbit-webdav/ jackrabbit-webdav/src/main/java/org/apache/jackrabbi...

Author: reschke
Date: Mon Sep 29 05:32:28 2008
New Revision: 700097

URL: http://svn.apache.org/viewvc?rev=700097&view=rev
Log:
JCR-1733: add support for WebDAV BIND protocol to simple webdav servlet, includes client compontents and test cases (requires the o.a.j.api.jsr283 extensions for shareable node support as defined in JSR-283)

Added:
    jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/
    jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindConstants.java   (with props)
    jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindInfo.java   (with props)
    jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindableResource.java   (with props)
    jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/ParentElement.java   (with props)
    jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/ParentSet.java   (with props)
    jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/RebindInfo.java   (with props)
    jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/UnbindInfo.java   (with props)
    jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/BindMethod.java   (with props)
    jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/UnbindMethod.java   (with props)
Modified:
    jackrabbit/trunk/jackrabbit-jcr-server/pom.xml
    jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DavResourceImpl.java   (contents, props changed)
    jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DeltaVResourceImpl.java
    jackrabbit/trunk/jackrabbit-webapp/src/main/webapp/webdav-simple.jsp
    jackrabbit/trunk/jackrabbit-webdav/README.txt
    jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavMethods.java   (contents, props changed)
    jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequest.java   (contents, props changed)
    jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequestImpl.java   (contents, props changed)
    jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyName.java   (contents, props changed)
    jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/AbstractWebdavServlet.java
    jackrabbit/trunk/jackrabbit-webdav/src/test/java/org/apache/jackrabbit/webdav/server/BindTest.java

Modified: jackrabbit/trunk/jackrabbit-jcr-server/pom.xml
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-server/pom.xml?rev=700097&r1=700096&r2=700097&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-server/pom.xml (original)
+++ jackrabbit/trunk/jackrabbit-jcr-server/pom.xml Mon Sep 29 05:32:28 2008
@@ -66,6 +66,11 @@
       <artifactId>jcr</artifactId>
     </dependency>
     <dependency>
+      <!-- temporarily added dependency, needed as long as JCR2 interfaces are contained in jackrabbit-api -->
+      <groupId>org.apache.jackrabbit</groupId>
+      <artifactId>jackrabbit-api</artifactId>
+    </dependency>
+    <dependency>
       <groupId>org.apache.jackrabbit</groupId>
       <artifactId>jackrabbit-jcr-commons</artifactId>
     </dependency>

Modified: jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DavResourceImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DavResourceImpl.java?rev=700097&r1=700096&r2=700097&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DavResourceImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DavResourceImpl.java Mon Sep 29 05:32:28 2008
@@ -39,6 +39,10 @@
 import org.apache.jackrabbit.webdav.DavServletResponse;
 import org.apache.jackrabbit.webdav.DavSession;
 import org.apache.jackrabbit.webdav.MultiStatusResponse;
+import org.apache.jackrabbit.webdav.bind.BindConstants;
+import org.apache.jackrabbit.webdav.bind.BindableResource;
+import org.apache.jackrabbit.webdav.bind.ParentSet;
+import org.apache.jackrabbit.webdav.bind.ParentElement;
 import org.apache.jackrabbit.webdav.io.InputContext;
 import org.apache.jackrabbit.webdav.io.OutputContext;
 import org.apache.jackrabbit.webdav.jcr.JcrDavException;
@@ -69,6 +73,7 @@
 import javax.jcr.PathNotFoundException;
 import javax.jcr.RepositoryException;
 import javax.jcr.Session;
+import javax.jcr.Workspace;
 import javax.jcr.lock.Lock;
 import java.io.IOException;
 import java.io.OutputStream;
@@ -78,17 +83,22 @@
 import java.util.Iterator;
 import java.util.List;
 import java.util.Map;
+import java.util.Set;
+import java.util.HashSet;
 
 /**
  * DavResourceImpl implements a DavResource.
  */
-public class DavResourceImpl implements DavResource, JcrConstants {
+public class DavResourceImpl implements DavResource, BindableResource, JcrConstants {
 
     /**
      * the default logger
      */
     private static final Logger log = LoggerFactory.getLogger(DavResourceImpl.class);
 
+    public static final String METHODS = DavResource.METHODS + ", " + BindConstants.METHODS;
+    public static final String COMPLIANCE_CLASS = DavResource.COMPLIANCE_CLASS + ", " + BindConstants.COMPLIANCE_CLASS;
+
     private DavResourceFactory factory;
     private LockManager lockManager;
     private JcrDavSession session;
@@ -196,7 +206,7 @@
      */
     private void initRfc4122Uri() {
         try {
-            if (node.isNodeType("mix:referenceable")) {
+            if (node.isNodeType(MIX_REFERENCEABLE)) {
                 String uuid = node.getUUID();
                 try {
                     UUID.fromString(uuid);
@@ -215,7 +225,7 @@
      * @see org.apache.jackrabbit.webdav.DavResource#getComplianceClass()
      */
     public String getComplianceClass() {
-        return DavResource.COMPLIANCE_CLASS;
+        return COMPLIANCE_CLASS;
     }
 
     /**
@@ -223,7 +233,7 @@
      * @see org.apache.jackrabbit.webdav.DavResource#getSupportedMethods()
      */
     public String getSupportedMethods() {
-        return DavResource.METHODS;
+        return METHODS;
     }
 
     /**
@@ -369,7 +379,12 @@
         }
 
         if (rfc4122Uri != null) {
-            properties.add(new HrefProperty(DavPropertyName.RESOURCEID, rfc4122Uri, true));
+            properties.add(new HrefProperty(BindConstants.RESOURCEID, rfc4122Uri, true));
+        }
+
+        Set parentElements = this.getParentElements();
+        if (!parentElements.isEmpty()) {
+            properties.add(new ParentSet(parentElements));
         }
 
         /* set current lock information. If no lock is set to this resource,
@@ -612,7 +627,13 @@
         try {
             String itemPath = member.getLocator().getRepositoryPath();
             Item memItem = getJcrSession().getItem(itemPath);
-            memItem.remove();
+            //TODO once jcr2 is out: simply call removeShare()
+            if (memItem instanceof org.apache.jackrabbit.api.jsr283.Node) {
+                org.apache.jackrabbit.api.jsr283.Node n = (org.apache.jackrabbit.api.jsr283.Node) memItem;
+                n.removeShare();
+            } else {
+                memItem.remove();
+            }
             getJcrSession().save();
 
             // make sure, non-jcr locks are removed, once the removal is completed
@@ -836,6 +857,98 @@
         return session;
     }
 
+
+    /**
+     * @see BindableResource#rebind(DavResource, DavResource)
+     */
+    public void bind(DavResource collection, DavResource newBinding) throws DavException {
+        if (!exists()) {
+            //DAV:bind-source-exists
+            throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED);
+        }
+        if (isLocked(collection)) {
+            //DAV:locked-update-allowed?
+            throw new DavException(DavServletResponse.SC_LOCKED);
+        }
+        if (isFilteredResource(newBinding)) {
+            throw new DavException(DavServletResponse.SC_FORBIDDEN);
+        }
+        checkSameWorkspace(collection.getLocator());
+        try {
+            if (!this.node.isNodeType(MIX_SHAREABLE)) {
+                if (!this.node.canAddMixin(MIX_SHAREABLE)) {
+                    //DAV:binding-allowed
+                    throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED);
+                }
+                this.node.addMixin(MIX_SHAREABLE);
+                this.node.save();
+            }
+            Workspace workspace = this.session.getRepositorySession().getWorkspace();
+            workspace.clone(workspace.getName(), this.node.getPath(), newBinding.getLocator().getRepositoryPath(), false);
+
+        } catch (RepositoryException e) {
+            throw new JcrDavException(e);
+        }
+
+    }
+
+    /**
+     * @see BindableResource#rebind(DavResource, DavResource)
+     */
+    public void rebind(DavResource collection, DavResource newBinding) throws DavException {
+        if (!exists()) {
+            //DAV:rebind-source-exists
+            throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED);
+        }
+        if (isLocked(this)) {
+            //DAV:protected-source-url-deletion.allowed
+            throw new DavException(DavServletResponse.SC_PRECONDITION_FAILED);
+        }
+        if (isLocked(collection)) {
+            //DAV:locked-update-allowed?
+            throw new DavException(DavServletResponse.SC_LOCKED);
+        }
+        if (isFilteredResource(newBinding)) {
+            throw new DavException(DavServletResponse.SC_FORBIDDEN);
+        }
+        checkSameWorkspace(collection.getLocator());
+        try {
+            if (!this.node.isNodeType(MIX_REFERENCEABLE)) {
+                throw new DavException(this.node.canAddMixin(MIX_REFERENCEABLE)?
+                                       DavServletResponse.SC_CONFLICT : DavServletResponse.SC_METHOD_NOT_ALLOWED);
+            }
+            getJcrSession().getWorkspace().move(locator.getRepositoryPath(), newBinding.getLocator().getRepositoryPath());
+        } catch (RepositoryException e) {
+            throw new JcrDavException(e);
+        }
+    }
+
+    /**
+     * @see org.apache.jackrabbit.webdav.bind.BindableResource#getParentElements()
+     */
+    public Set getParentElements() {
+        try {
+            //TODO remove this check once jcr2 is out
+            if (!(this.node instanceof org.apache.jackrabbit.api.jsr283.Node)) {
+                DavResourceLocator loc = this.locator.getFactory().createResourceLocator(
+                        this.locator.getPrefix(), this.locator.getWorkspacePath(), this.node.getParent().getPath(), false);
+                return Collections.singleton(new ParentElement(loc.getHref(true), this.node.getName()));
+            }
+            Set ps = new HashSet();
+            NodeIterator sharedSetIterator = ((org.apache.jackrabbit.api.jsr283.Node) this.node).getSharedSet();
+            while (sharedSetIterator.hasNext()) {
+                Node sharednode = sharedSetIterator.nextNode();
+                DavResourceLocator loc = this.locator.getFactory().createResourceLocator(
+                        this.locator.getPrefix(), this.locator.getWorkspacePath(), sharednode.getParent().getPath(), false);
+                ps.add(new ParentElement(loc.getHref(true), sharednode.getName()));
+            }
+            return ps;
+        } catch (RepositoryException e) {
+            log.warn("unable to calculate parent set", e);
+            return Collections.EMPTY_SET; 
+        }
+    }
+
     /**
      * Returns the node that is wrapped by this resource.
      *

Propchange: jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DavResourceImpl.java
            ('svn' removed)

Modified: jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DeltaVResourceImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DeltaVResourceImpl.java?rev=700097&r1=700096&r2=700097&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DeltaVResourceImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-jcr-server/src/main/java/org/apache/jackrabbit/webdav/simple/DeltaVResourceImpl.java Mon Sep 29 05:32:28 2008
@@ -32,6 +32,7 @@
 import org.apache.jackrabbit.webdav.DavServletResponse;
 import org.apache.jackrabbit.webdav.DavSession;
 import org.apache.jackrabbit.webdav.DavCompliance;
+import org.apache.jackrabbit.webdav.bind.BindConstants;
 import org.apache.jackrabbit.webdav.property.DavProperty;
 import org.apache.jackrabbit.webdav.property.DavPropertyName;
 import org.apache.jackrabbit.webdav.property.HrefProperty;
@@ -77,7 +78,8 @@
                 DavCompliance._2_,
                 DavCompliance.VERSION_CONTROL,
                 DavCompliance.VERSION_HISTORY,
-                DavCompliance.LABEL
+                DavCompliance.LABEL,
+                BindConstants.COMPLIANCE_CLASS,
         });
     }
 

Modified: jackrabbit/trunk/jackrabbit-webapp/src/main/webapp/webdav-simple.jsp
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-webapp/src/main/webapp/webdav-simple.jsp?rev=700097&r1=700096&r2=700097&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-webapp/src/main/webapp/webdav-simple.jsp (original)
+++ jackrabbit/trunk/jackrabbit-webapp/src/main/webapp/webdav-simple.jsp Mon Sep 29 05:32:28 2008
@@ -28,7 +28,7 @@
 
 <p>
   The default WebDAV server (aka: Simple Server) is a
-  <a href="http://www.ietf.org/rfc/rfc2518.txt">DAV1,2</a> and
+  <a href="http://www.ietf.org/rfc/rfc2518.txt">DAV 1,2</a> and
   <a href="http://www.ietf.org/rfc/rfc3253.txt">DeltaV</a>
   compliant WebDAV  server implementation. It offers a file-based view to
   the JCR repository, suitable  for everybody looking for standard WebDAV
@@ -71,6 +71,7 @@
 <ul>
 <li><a href="http://www.ietf.org/rfc/rfc2518.txt">RFC 2518</a> (WebDAV 1,2)</li>
 <li><a href="http://www.ietf.org/rfc/rfc3253.txt">RFC 3253</a> (DeltaV)</li>
+<li>Experimental: <a href="http://greenbytes.de/tech/webdav/draft-ietf-webdav-bind-latest.html">draft-ietf-webdav-bind</a> (WebDAV BIND)</li>
 </ul> 
 
 <h3>Configuration</h3>

Modified: jackrabbit/trunk/jackrabbit-webdav/README.txt
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-webdav/README.txt?rev=700097&r1=700096&r2=700097&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-webdav/README.txt (original)
+++ jackrabbit/trunk/jackrabbit-webdav/README.txt Mon Sep 29 05:32:28 2008
@@ -11,6 +11,7 @@
     * RFC 3648 (Ordered Collections Protocol)
     * RFC 3744 (Access Control Protocol)
     * DAV Searching and Locating  (DASL)
+    * Binding Extensions to Web Distributed Authoring and Versioning (WebDAV) (experimental)
 
 In addition this library defines (unspecified)
 
@@ -82,9 +83,9 @@
 ================
 
 Q: Which WebDAV features are supported?
-A: DAV1,2, DeltaV, Ordering, Access Control, Search
+A: DAV 1, 2, DeltaV, Ordering, Access Control, Search, Bind
 
-Q: This this WebDAV libarary provide a full dav server?
+Q: This this WebDAV library provide a full dav server?
 A: This library only defines interfaces, utilities and common
    classes used for a dav server/client.
    A JCR specific implementation can be found in the 'jcr-server'

Modified: jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavMethods.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavMethods.java?rev=700097&r1=700096&r2=700097&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavMethods.java (original)
+++ jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavMethods.java Mon Sep 29 05:32:28 2008
@@ -262,6 +262,27 @@
     public static final String METHOD_ACL = "ACL";
 
     /**
+     * The webdav REBIND method and public constant defined by
+     * the BIND specification
+     */
+    public static final int DAV_REBIND = DAV_ACL + 1;
+    public static final String METHOD_REBIND = "REBIND";
+
+    /**
+     * The webdav UNBIND method and public constant defined by
+     * the BIND specification
+     */
+    public static final int DAV_UNBIND = DAV_REBIND + 1;
+    public static final String METHOD_UNBIND = "UNBIND";
+
+    /**
+     * The webdav BIND method and public constant defined by
+     * the BIND specification
+     */
+    public static final int DAV_BIND = DAV_UNBIND + 1;
+    public static final String METHOD_BIND = "BIND";
+
+    /**
      * Returns webdav method type code, error result <= 0
      * Valid type codes > 0
      */
@@ -314,6 +335,9 @@
         addMethodCode(METHOD_BASELINE_CONTROL, DAV_BASELINE_CONTROL);
         addMethodCode(METHOD_MKACTIVITY, DAV_MKACTIVITY);
         addMethodCode(METHOD_ACL, DAV_ACL);
+        addMethodCode(METHOD_REBIND, DAV_REBIND);
+        addMethodCode(METHOD_UNBIND, DAV_UNBIND);
+        addMethodCode(METHOD_BIND, DAV_BIND);
 
         labelMethods = new int[] { DAV_GET, DAV_HEAD, DAV_OPTIONS, DAV_PROPFIND,
                                    DAV_LABEL, DAV_COPY };
@@ -381,4 +405,4 @@
         }
         return false;
     }
-}
\ No newline at end of file
+}

Propchange: jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/DavMethods.java
            ('svn' removed)

Modified: jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequest.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequest.java?rev=700097&r1=700096&r2=700097&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequest.java (original)
+++ jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequest.java Mon Sep 29 05:32:28 2008
@@ -20,6 +20,7 @@
 import org.apache.jackrabbit.webdav.ordering.OrderingDavServletRequest;
 import org.apache.jackrabbit.webdav.transaction.TransactionDavServletRequest;
 import org.apache.jackrabbit.webdav.version.DeltaVServletRequest;
+import org.apache.jackrabbit.webdav.bind.BindServletRequest;
 
 /**
  * The empty <code>WebdavRequest</code> interface collects the functionality
@@ -30,5 +31,6 @@
  */
 public interface WebdavRequest extends DavServletRequest,
         ObservationDavServletRequest, OrderingDavServletRequest,
-        TransactionDavServletRequest, DeltaVServletRequest {
-}
\ No newline at end of file
+        TransactionDavServletRequest, DeltaVServletRequest,
+        BindServletRequest {
+}

Propchange: jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequest.java
            ('svn' removed)

Modified: jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequestImpl.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequestImpl.java?rev=700097&r1=700096&r2=700097&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequestImpl.java (original)
+++ jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequestImpl.java Mon Sep 29 05:32:28 2008
@@ -45,6 +45,9 @@
 import org.apache.jackrabbit.webdav.version.report.ReportInfo;
 import org.apache.jackrabbit.webdav.xml.DomUtil;
 import org.apache.jackrabbit.webdav.xml.ElementIterator;
+import org.apache.jackrabbit.webdav.bind.RebindInfo;
+import org.apache.jackrabbit.webdav.bind.UnbindInfo;
+import org.apache.jackrabbit.webdav.bind.BindInfo;
 import org.slf4j.Logger;
 import org.slf4j.LoggerFactory;
 import org.w3c.dom.Document;
@@ -189,6 +192,59 @@
     }
 
     /**
+     * Parse a href and return the path of the resource.
+     *
+     * @return path of the resource identified by the href.
+     * @see org.apache.jackrabbit.webdav.bind.BindServletRequest#getHrefLocator
+     */
+    public DavResourceLocator getHrefLocator(String href) throws DavException {
+        String ref = href;
+        if (ref != null) {
+            //href should be a Simple-ref production as defined in RFC4918, so it is either an absolute URI
+            //or an absoltute path
+            try {
+                URI uri = new URI(ref);
+                String auth = uri.getAuthority();
+                ref = uri.getRawPath();
+                if (auth == null) {
+                    //verify that href is an absolute path
+                    if (ref.startsWith("//") || !ref.startsWith("/")) {
+                        log.warn("expected absolute path but found " + ref);
+                        throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+                    }
+                } else if (!auth.equals(httpRequest.getHeader("Host"))) {
+                    //this looks like an unsupported cross-server operation, but of course a reverse-proxy
+                    //might have rewritten the Host header. Since we can't find out, we have to reject anyway.
+                    //Better use absolute paths in DAV:href elements!
+                    throw new DavException(DavServletResponse.SC_FORBIDDEN);
+                }
+            } catch (URISyntaxException e) {
+                log.warn("malformed uri: " + href, e);
+                throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+            }
+            // cut off the context path
+            String contextPath = httpRequest.getContextPath();
+            if (ref.startsWith(contextPath)) {
+                ref = ref.substring(contextPath.length());
+            } else {
+                //absolute path has to start with contextpath
+                throw new DavException(DavServletResponse.SC_FORBIDDEN);
+            }
+        }
+        return factory.createResourceLocator(hrefPrefix, ref);
+    }
+
+    /**
+     * Returns the path of the member resource of the request resource which is identified by the segment parameter.
+     *
+     * @return path of internal member resource.
+     */
+    public DavResourceLocator getMemberLocator(String segment) {
+        String path = (this.getRequestLocator().getHref(true) + segment).substring(hrefPrefix.length());
+        return factory.createResourceLocator(hrefPrefix, path);
+    }
+
+    /**
      * Return true if the overwrite header does not inhibit overwriting.
      *
      * @return true if the overwrite header requests 'overwriting'
@@ -726,6 +782,42 @@
         return info;
     }
 
+    /**
+     * @see org.apache.jackrabbit.webdav.bind.BindServletRequest#getRebindInfo()
+     */
+    public RebindInfo getRebindInfo() throws DavException {
+        RebindInfo info = null;
+        Document requestDocument = getRequestDocument();
+        if (requestDocument != null) {
+            info = RebindInfo.createFromXml(requestDocument.getDocumentElement());
+        }
+        return info;
+    }
+
+    /**
+     * @see org.apache.jackrabbit.webdav.bind.BindServletRequest#getUnbindInfo()
+     */
+    public UnbindInfo getUnbindInfo() throws DavException {
+        UnbindInfo info = null;
+        Document requestDocument = getRequestDocument();
+        if (requestDocument != null) {
+            info = UnbindInfo.createFromXml(requestDocument.getDocumentElement());
+        }
+        return info;
+    }
+
+    /**
+     * @see org.apache.jackrabbit.webdav.bind.BindServletRequest#getBindInfo()
+     */
+    public BindInfo getBindInfo() throws DavException {
+        BindInfo info = null;
+        Document requestDocument = getRequestDocument();
+        if (requestDocument != null) {
+            info = BindInfo.createFromXml(requestDocument.getDocumentElement());
+        }
+        return info;
+    }
+
     //---------------------------------------< HttpServletRequest interface >---
     public String getAuthType() {
         return httpRequest.getAuthType();
@@ -926,4 +1018,4 @@
     public String getRealPath(String s) {
         return httpRequest.getRealPath(s);
     }
-}
\ No newline at end of file
+}

Propchange: jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/WebdavRequestImpl.java
            ('svn' removed)

Added: jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindConstants.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindConstants.java?rev=700097&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindConstants.java (added)
+++ jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindConstants.java Mon Sep 29 05:32:28 2008
@@ -0,0 +1,54 @@
+/*
+ * 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.jackrabbit.webdav.bind;
+
+import org.apache.jackrabbit.webdav.xml.Namespace;
+import org.apache.jackrabbit.webdav.DavConstants;
+import org.apache.jackrabbit.webdav.property.DavPropertyName;
+
+/**
+ * <code>BindConstants</code> provide constants for request and response
+ * headers, Xml elements and property names defined by
+ * the BIND specification.
+ */
+public interface BindConstants {
+
+    /**
+     * The namespace
+     */
+    public static final Namespace NAMESPACE = DavConstants.NAMESPACE;
+
+    /**
+     * local names of XML elements used in the request bodies of the methods BIND, REBIND and UNBIND.
+     */
+    public static final String XML_BIND = "bind";
+    public static final String XML_REBIND = "rebind";
+    public static final String XML_UNBIND = "unbind";
+    public static final String XML_SEGMENT = "segment";
+    public static final String XML_HREF = "href";
+    public static final String XML_PARENT = "parent";
+
+    public static final String METHODS = "BIND, REBIND, UNBIND";
+
+    public static final String COMPLIANCE_CLASS = "bind";
+
+    /*
+     * Webdav properties defined by the BIND specification. 
+     */
+    public static final DavPropertyName RESOURCEID = DavPropertyName.create("resource-id");
+    public static final DavPropertyName PARENTSET = DavPropertyName.create("parent-set");
+}

Propchange: jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindConstants.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindInfo.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindInfo.java?rev=700097&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindInfo.java (added)
+++ jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindInfo.java Mon Sep 29 05:32:28 2008
@@ -0,0 +1,108 @@
+/*
+ * 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.jackrabbit.webdav.bind;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.xml.DomUtil;
+import org.apache.jackrabbit.webdav.xml.ElementIterator;
+import org.apache.jackrabbit.webdav.xml.XmlSerializable;
+import org.w3c.dom.Element;
+import org.w3c.dom.Document;
+
+public class BindInfo implements XmlSerializable {
+
+    private static Logger log = LoggerFactory.getLogger(BindInfo.class);
+
+    private String segment;
+    private String href;
+
+    public BindInfo(String href, String segment) {
+        this.href = href;
+        this.segment = segment;
+    }
+
+    public String getHref() {
+        return this.href;
+    }
+
+    public String getSegment() {
+        return this.segment;
+    }
+
+    /**
+     * Build an <code>BindInfo</code> object from the root element present
+     * in the request body.
+     *
+     * @param root the root element of the request body
+     * @return a BindInfo object containing segment and href
+     * @throws org.apache.jackrabbit.webdav.DavException if the BIND request is malformed
+     */
+    public static BindInfo createFromXml(Element root) throws DavException {
+        if (!DomUtil.matches(root, BindConstants.XML_BIND, BindConstants.NAMESPACE)) {
+            log.warn("DAV:bind element expected");
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+        }
+        String href = null;
+        String segment = null;
+        ElementIterator it = DomUtil.getChildren(root);
+        while (it.hasNext()) {
+            Element elt = it.nextElement();
+            if (DomUtil.matches(elt, BindConstants.XML_SEGMENT, BindConstants.NAMESPACE)) {
+                if (segment == null) {
+                    segment = DomUtil.getText(elt);
+                } else {
+                    log.warn("unexpected multiple occurence of DAV:segment element");
+                    throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+                }
+            } else if (DomUtil.matches(elt, BindConstants.XML_HREF, BindConstants.NAMESPACE)) {
+                if (href == null) {
+                    href = DomUtil.getText(elt);
+                } else {
+                    log.warn("unexpected multiple occurence of DAV:href element");
+                    throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+                }
+            } else  {
+                log.warn("unexpected element " + elt.getLocalName());
+                throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+            }
+        }
+        if (href == null) {
+            log.warn("DAV:href element expected");
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+        }
+        if (segment == null) {
+            log.warn("DAV:segment element expected");
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+        }
+        return new BindInfo(href, segment);
+    }
+
+    /**
+     * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(org.w3c.dom.Document)
+     */
+    public Element toXml(Document document) {
+        Element bindElt = DomUtil.createElement(document, BindConstants.XML_BIND, BindConstants.NAMESPACE);
+        Element hrefElt = DomUtil.createElement(document, BindConstants.XML_HREF, BindConstants.NAMESPACE, this.href);
+        Element segElt = DomUtil.createElement(document, BindConstants.XML_SEGMENT, BindConstants.NAMESPACE, this.segment);
+        bindElt.appendChild(hrefElt);
+        bindElt.appendChild(segElt);
+        return bindElt;
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindInfo.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindableResource.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindableResource.java?rev=700097&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindableResource.java (added)
+++ jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindableResource.java Mon Sep 29 05:32:28 2008
@@ -0,0 +1,49 @@
+/*
+ * 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.jackrabbit.webdav.bind;
+
+import org.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.DavResource;
+
+import java.util.Collection;
+import java.util.Set;
+
+public interface BindableResource {
+
+    /**
+     * Will add a new binding to the given collection referencing this resource.
+     *
+     * @param collection the collection to create the new binding in.
+     * @param newBinding the new binding
+     */
+    public void bind(DavResource collection, DavResource newBinding) throws DavException;
+
+    /**
+     * Will rebind the resource to the given collection. By definition, this is an atomic move operation.
+     *
+     * @param collection the collection to create the new binding in.
+     * @param newBinding the new binding
+     */
+    public void rebind(DavResource collection, DavResource newBinding) throws DavException;
+
+    /**
+     * Will retrieve a collection of parent elements of the bindable resource representing the parent set.
+     *
+     * @return newBinding the new binding
+     */
+    public Set getParentElements();
+}

Propchange: jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/BindableResource.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/ParentElement.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/ParentElement.java?rev=700097&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/ParentElement.java (added)
+++ jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/ParentElement.java Mon Sep 29 05:32:28 2008
@@ -0,0 +1,111 @@
+/*
+ * 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.jackrabbit.webdav.bind;
+
+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.DavException;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.w3c.dom.Element;
+import org.w3c.dom.Document;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * <code>ParentElement</code> wraps en element of the parent set of a resource. A <code>java.util.Set</code> of
+ * <code>ParentElement</code> objects may serve as the value object of the <code>ParentSet</code> DavProperty.
+ */
+public class ParentElement implements XmlSerializable {
+
+    private static Logger log = LoggerFactory.getLogger(ParentElement.class);
+
+    private final String href;
+    private final String segment;
+
+    public ParentElement(String href, String segment) {
+        this.href = href;
+        this.segment = segment;
+    }
+
+    public String getHref() {
+        return this.href;
+    }
+
+    public String getSegment() {
+        return this.segment;
+    }
+
+    /**
+     * Build an <code>ParentElement</code> object from an XML element DAV:parent
+     *
+     * @param root the DAV:parent element
+     * @return a ParentElement object
+     * @throws org.apache.jackrabbit.webdav.DavException if the DAV:parent element is malformed
+     */
+    public static ParentElement createFromXml(Element root) throws DavException {
+        if (!DomUtil.matches(root, BindConstants.XML_PARENT, BindConstants.NAMESPACE)) {
+            log.warn("DAV:paret element expected");
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+        }
+        String href = null;
+        String segment = null;
+        ElementIterator it = DomUtil.getChildren(root);
+        while (it.hasNext()) {
+            Element elt = it.nextElement();
+            if (DomUtil.matches(elt, BindConstants.XML_SEGMENT, BindConstants.NAMESPACE)) {
+                if (segment == null) {
+                    segment = DomUtil.getText(elt);
+                } else {
+                    log.warn("unexpected multiple occurence of DAV:segment element");
+                    throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+                }
+            } else if (DomUtil.matches(elt, BindConstants.XML_HREF, BindConstants.NAMESPACE)) {
+                if (href == null) {
+                    href = DomUtil.getText(elt);
+                } else {
+                    log.warn("unexpected multiple occurence of DAV:href element");
+                    throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+                }
+            } else  {
+                log.warn("unexpected element " + elt.getLocalName());
+                throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+            }
+        }
+        if (href == null) {
+            log.warn("DAV:href element expected");
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+        }
+        if (segment == null) {
+            log.warn("DAV:segment element expected");
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+        }
+        return new ParentElement(href, segment);
+    }
+
+    /**
+     * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(org.w3c.dom.Document)  
+     */
+    public Element toXml(Document document) {
+        Element parentElt = DomUtil.createElement(document, BindConstants.XML_PARENT, BindConstants.NAMESPACE);
+        Element hrefElt = DomUtil.createElement(document, BindConstants.XML_HREF, BindConstants.NAMESPACE, this.href);
+        Element segElt = DomUtil.createElement(document, BindConstants.XML_SEGMENT, BindConstants.NAMESPACE, this.segment);
+        parentElt.appendChild(hrefElt);
+        parentElt.appendChild(segElt);
+        return parentElt;
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/ParentElement.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/ParentSet.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/ParentSet.java?rev=700097&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/ParentSet.java (added)
+++ jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/ParentSet.java Mon Sep 29 05:32:28 2008
@@ -0,0 +1,53 @@
+/*
+ * 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.jackrabbit.webdav.bind;
+
+import org.apache.jackrabbit.webdav.xml.XmlSerializable;
+import org.apache.jackrabbit.webdav.xml.DomUtil;
+import org.apache.jackrabbit.webdav.property.AbstractDavProperty;
+import org.apache.jackrabbit.webdav.property.DavPropertyName;
+import org.w3c.dom.Element;
+import org.w3c.dom.Document;
+import org.w3c.dom.Node;
+
+import java.util.Collection;
+import java.util.Collections;
+import java.util.List;
+
+/**
+ * <code>ParentSet</code> represents a DAV:parent-set property.
+ */
+public class ParentSet extends AbstractDavProperty {
+
+    private final Collection parents;
+
+    /**
+     * Creates a new ParentSet from a collection of <code>ParentElement</code> objects.
+     * @param parents
+     */
+    public ParentSet(Collection parents) {
+        super(BindConstants.PARENTSET, true);
+        this.parents = parents;
+    }
+
+    /**
+     * @see org.apache.jackrabbit.webdav.property.AbstractDavProperty#getValue() 
+     */
+    public Object getValue() {
+        return this.parents;
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/ParentSet.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/RebindInfo.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/RebindInfo.java?rev=700097&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/RebindInfo.java (added)
+++ jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/RebindInfo.java Mon Sep 29 05:32:28 2008
@@ -0,0 +1,108 @@
+/*
+ * 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.jackrabbit.webdav.bind;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.xml.DomUtil;
+import org.apache.jackrabbit.webdav.xml.ElementIterator;
+import org.apache.jackrabbit.webdav.xml.XmlSerializable;
+import org.w3c.dom.Element;
+import org.w3c.dom.Document;
+
+public class RebindInfo implements XmlSerializable {
+
+    private static Logger log = LoggerFactory.getLogger(RebindInfo.class);
+
+    private String segment;
+    private String href;
+
+    public RebindInfo(String href, String segment) {
+        this.href = href;
+        this.segment = segment;
+    }
+
+    public String getHref() {
+        return this.href;
+    }
+
+    public String getSegment() {
+        return this.segment;
+    }
+
+    /**
+     * Build an <code>RebindInfo</code> object from the root element present
+     * in the request body.
+     *
+     * @param root the root element of the request body
+     * @return a RebindInfo object containing segment and href
+     * @throws org.apache.jackrabbit.webdav.DavException if the REBIND request is malformed 
+     */
+    public static RebindInfo createFromXml(Element root) throws DavException {
+        if (!DomUtil.matches(root, BindConstants.XML_REBIND, BindConstants.NAMESPACE)) {
+            log.warn("DAV:rebind element expected");
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+        }
+        String href = null;
+        String segment = null;
+        ElementIterator it = DomUtil.getChildren(root);
+        while (it.hasNext()) {
+            Element elt = it.nextElement();
+            if (DomUtil.matches(elt, BindConstants.XML_SEGMENT, BindConstants.NAMESPACE)) {
+                if (segment == null) {
+                    segment = DomUtil.getText(elt);
+                } else {
+                    log.warn("unexpected multiple occurence of DAV:segment element");
+                    throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+                }
+            } else if (DomUtil.matches(elt, BindConstants.XML_HREF, BindConstants.NAMESPACE)) {
+                if (href == null) {
+                    href = DomUtil.getText(elt);
+                } else {
+                    log.warn("unexpected multiple occurence of DAV:href element");
+                    throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+                }
+            } else  {
+                log.warn("unexpected element " + elt.getLocalName());
+                throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+            }
+        }
+        if (href == null) {
+            log.warn("DAV:href element expected");
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+        }
+        if (segment == null) {
+            log.warn("DAV:segment element expected");
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+        }
+        return new RebindInfo(href, segment);
+    }
+
+    /**
+     * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(org.w3c.dom.Document)
+     */
+    public Element toXml(Document document) {
+        Element rebindElt = DomUtil.createElement(document, BindConstants.XML_REBIND, BindConstants.NAMESPACE);
+        Element hrefElt = DomUtil.createElement(document, BindConstants.XML_HREF, BindConstants.NAMESPACE, this.href);
+        Element segElt = DomUtil.createElement(document, BindConstants.XML_SEGMENT, BindConstants.NAMESPACE, this.segment);
+        rebindElt.appendChild(hrefElt);
+        rebindElt.appendChild(segElt);
+        return rebindElt;
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/RebindInfo.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/UnbindInfo.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/UnbindInfo.java?rev=700097&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/UnbindInfo.java (added)
+++ jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/UnbindInfo.java Mon Sep 29 05:32:28 2008
@@ -0,0 +1,90 @@
+/*
+ * 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.jackrabbit.webdav.bind;
+
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+import org.apache.jackrabbit.webdav.DavException;
+import org.apache.jackrabbit.webdav.xml.DomUtil;
+import org.apache.jackrabbit.webdav.xml.ElementIterator;
+import org.apache.jackrabbit.webdav.xml.XmlSerializable;
+import org.w3c.dom.Element;
+import org.w3c.dom.Document;
+
+public class UnbindInfo implements XmlSerializable {
+
+    private static Logger log = LoggerFactory.getLogger(UnbindInfo.class);
+
+    private String segment;
+
+    private UnbindInfo() {}
+
+    public UnbindInfo(String segment) {
+        this.segment = segment;
+    }
+
+    public String getSegment() {
+        return this.segment;
+    }
+
+    /**
+     * Build an <code>UnbindInfo</code> object from the root element present
+     * in the request body.
+     *
+     * @param root the root element of the request body
+     * @return a UnbindInfo object containing a segment identifier
+     * @throws org.apache.jackrabbit.webdav.DavException if the UNBIND request is malformed
+     */
+    public static UnbindInfo createFromXml(Element root) throws DavException {
+        if (!DomUtil.matches(root, BindConstants.XML_UNBIND, BindConstants.NAMESPACE)) {
+            log.warn("DAV:unbind element expected");
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+        }
+        String segment = null;
+        ElementIterator it = DomUtil.getChildren(root);
+        while (it.hasNext()) {
+            Element elt = it.nextElement();
+            if (DomUtil.matches(elt, BindConstants.XML_SEGMENT, BindConstants.NAMESPACE)) {
+                if (segment == null) {
+                    segment = DomUtil.getText(elt);
+                } else {
+                    log.warn("unexpected multiple occurence of DAV:segment element");
+                    throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+                }
+            } else  {
+                log.warn("unexpected element " + elt.getLocalName());
+                throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+            }
+        }
+        if (segment == null) {
+            log.warn("DAV:segment element expected");
+            throw new DavException(DavServletResponse.SC_BAD_REQUEST);
+        }
+        return new UnbindInfo(segment);
+    }
+
+    /**
+     * @see org.apache.jackrabbit.webdav.xml.XmlSerializable#toXml(org.w3c.dom.Document)
+     */
+    public Element toXml(Document document) {
+        Element unbindElt = DomUtil.createElement(document, BindConstants.XML_UNBIND, BindConstants.NAMESPACE);
+        Element segElt = DomUtil.createElement(document, BindConstants.XML_SEGMENT, BindConstants.NAMESPACE, this.segment);
+        unbindElt.appendChild(segElt);
+        return unbindElt;
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/bind/UnbindInfo.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/BindMethod.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/BindMethod.java?rev=700097&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/BindMethod.java (added)
+++ jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/BindMethod.java Mon Sep 29 05:32:28 2008
@@ -0,0 +1,51 @@
+/*
+ * 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.jackrabbit.webdav.client.methods;
+
+import org.apache.jackrabbit.webdav.bind.BindInfo;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+
+import java.io.IOException;
+
+/**
+ * <code>BindMethod</code> creates a new binding to a resource.
+ */
+public class BindMethod extends DavMethodBase {
+
+    public BindMethod(String uri, BindInfo info) throws IOException {
+        super(uri);
+        setRequestBody(info);
+    }
+
+    //---------------------------------------------------------< HttpMethod >---
+    /**
+     * @see org.apache.commons.httpclient.HttpMethod#getName()
+     */
+    public String getName() {
+        return "BIND";
+    }
+
+    //------------------------------------------------------< DavMethodBase >---
+    /**
+     *
+     * @param statusCode
+     * @return true if status code is 200 (existing binding was overwritten) or 201 (new binding created).
+     */
+    protected boolean isSuccess(int statusCode) {
+        return statusCode == DavServletResponse.SC_CREATED || statusCode == DavServletResponse.SC_OK;
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/BindMethod.java
------------------------------------------------------------------------------
    svn:eol-style = native

Added: jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/UnbindMethod.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/UnbindMethod.java?rev=700097&view=auto
==============================================================================
--- jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/UnbindMethod.java (added)
+++ jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/UnbindMethod.java Mon Sep 29 05:32:28 2008
@@ -0,0 +1,51 @@
+/*
+ * 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.jackrabbit.webdav.client.methods;
+
+import org.apache.jackrabbit.webdav.bind.UnbindInfo;
+import org.apache.jackrabbit.webdav.DavServletResponse;
+
+import java.io.IOException;
+
+/**
+ * <code>UnbindMethod</code> removes a binding to a resource (semantically equivalent to delete).
+ */
+public class UnbindMethod extends DavMethodBase {
+
+    public UnbindMethod(String uri, UnbindInfo info) throws IOException {
+        super(uri);
+        setRequestBody(info);
+    }
+
+    //---------------------------------------------------------< HttpMethod >---
+    /**
+     * @see org.apache.commons.httpclient.HttpMethod#getName()
+     */
+    public String getName() {
+        return "UNBIND";
+    }
+
+    //------------------------------------------------------< DavMethodBase >---
+    /**
+     *
+     * @param statusCode
+     * @return true if status code is 200 (binding was removed).
+     */
+    protected boolean isSuccess(int statusCode) {
+        return statusCode == DavServletResponse.SC_OK;
+    }
+}

Propchange: jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/client/methods/UnbindMethod.java
------------------------------------------------------------------------------
    svn:eol-style = native

Modified: jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyName.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyName.java?rev=700097&r1=700096&r2=700097&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyName.java (original)
+++ jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyName.java Mon Sep 29 05:32:28 2008
@@ -49,9 +49,6 @@
     public static final DavPropertyName SOURCE = DavPropertyName.create(PROPERTY_SOURCE);
     public static final DavPropertyName SUPPORTEDLOCK = DavPropertyName.create(PROPERTY_SUPPORTEDLOCK);
 
-    /* webdav properties defined by the BIND specification */
-    public static final DavPropertyName RESOURCEID = DavPropertyName.create(PROPERTY_RESOURCEID);
-
     /* property use by microsoft that are not specified in the RFC 2518 */
     public static final DavPropertyName ISCOLLECTION = DavPropertyName.create("iscollection");
 

Propchange: jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/property/DavPropertyName.java
            ('svn' removed)

Modified: jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/AbstractWebdavServlet.java
URL: http://svn.apache.org/viewvc/jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/AbstractWebdavServlet.java?rev=700097&r1=700096&r2=700097&view=diff
==============================================================================
--- jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/AbstractWebdavServlet.java (original)
+++ jackrabbit/trunk/jackrabbit-webdav/src/main/java/org/apache/jackrabbit/webdav/server/AbstractWebdavServlet.java Mon Sep 29 05:32:28 2008
@@ -32,6 +32,10 @@
 import org.apache.jackrabbit.webdav.WebdavRequestImpl;
 import org.apache.jackrabbit.webdav.WebdavResponse;
 import org.apache.jackrabbit.webdav.WebdavResponseImpl;
+import org.apache.jackrabbit.webdav.bind.RebindInfo;
+import org.apache.jackrabbit.webdav.bind.UnbindInfo;
+import org.apache.jackrabbit.webdav.bind.BindableResource;
+import org.apache.jackrabbit.webdav.bind.BindInfo;
 import org.apache.jackrabbit.webdav.io.InputContext;
 import org.apache.jackrabbit.webdav.io.InputContextImpl;
 import org.apache.jackrabbit.webdav.io.OutputContext;
@@ -311,6 +315,15 @@
             case DavMethods.DAV_ACL:
                 doAcl(request, response, resource);
                 break;
+            case DavMethods.DAV_REBIND:
+                doRebind(request, response, resource);
+                break;
+            case DavMethods.DAV_UNBIND:
+                doUnbind(request, response, resource);
+                break;
+            case DavMethods.DAV_BIND:
+                doBind(request, response, resource);
+                break;
             default:
                 // any other method
                 return false;
@@ -575,7 +588,7 @@
         }
 
         DavResource destResource = getResourceFactory().createResource(request.getDestinationLocator(), request, response);
-        int status = validateDestination(destResource, request);
+        int status = validateDestination(destResource, request, true);
         if (status > DavServletResponse.SC_NO_CONTENT) {
             response.sendError(status);
             return;
@@ -598,7 +611,7 @@
                           DavResource resource) throws IOException, DavException {
 
         DavResource destResource = getResourceFactory().createResource(request.getDestinationLocator(), request, response);
-        int status = validateDestination(destResource, request);
+        int status = validateDestination(destResource, request, true);
         if (status > DavServletResponse.SC_NO_CONTENT) {
             response.sendError(status);
             return;
@@ -609,6 +622,85 @@
     }
 
     /**
+     * The BIND method
+     *
+     * @param request
+     * @param response
+     * @param resource the collection resource to which a new member will be added
+     * @throws IOException
+     * @throws DavException
+     */
+    protected void doBind(WebdavRequest request, WebdavResponse response,
+                          DavResource resource) throws IOException, DavException {
+
+        if (!resource.exists()) {
+            response.sendError(DavServletResponse.SC_NOT_FOUND);
+        }
+        BindInfo bindInfo = request.getBindInfo();
+        DavResource oldBinding = getResourceFactory().createResource(request.getHrefLocator(bindInfo.getHref()), request, response);
+        if (!(oldBinding instanceof BindableResource)) {
+            response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED);
+            return;
+        }
+        DavResource newBinding = getResourceFactory().createResource(request.getMemberLocator(bindInfo.getSegment()), request, response);
+        int status = validateDestination(newBinding, request, false);
+        if (status > DavServletResponse.SC_NO_CONTENT) {
+            response.sendError(status);
+            return;
+        }
+        ((BindableResource) oldBinding).bind(resource, newBinding);
+        response.setStatus(status);
+    }
+
+    /**
+     * The REBIND method
+     *
+     * @param request
+     * @param response
+     * @param resource the collection resource to which a new member will be added
+     * @throws IOException
+     * @throws DavException
+     */
+    protected void doRebind(WebdavRequest request, WebdavResponse response,
+                            DavResource resource) throws IOException, DavException {
+
+        if (!resource.exists()) {
+            response.sendError(DavServletResponse.SC_NOT_FOUND);
+        }
+        RebindInfo rebindInfo = request.getRebindInfo();
+        DavResource oldBinding = getResourceFactory().createResource(request.getHrefLocator(rebindInfo.getHref()), request, response);
+        if (!(oldBinding instanceof BindableResource)) {
+            response.sendError(DavServletResponse.SC_METHOD_NOT_ALLOWED);
+            return;
+        }
+        DavResource newBinding = getResourceFactory().createResource(request.getMemberLocator(rebindInfo.getSegment()), request, response);
+        int status = validateDestination(newBinding, request, false);
+        if (status > DavServletResponse.SC_NO_CONTENT) {
+            response.sendError(status);
+            return;
+        }
+        ((BindableResource) oldBinding).rebind(resource, newBinding);
+        response.setStatus(status);
+    }
+
+    /**
+     * The UNBIND method
+     *
+     * @param request
+     * @param response
+     * @param resource the collection resource from which a member will be removed
+     * @throws IOException
+     * @throws DavException
+     */
+    protected void doUnbind(WebdavRequest request, WebdavResponse response,
+                            DavResource resource) throws IOException, DavException {
+
+        UnbindInfo unbindInfo = request.getUnbindInfo();
+        DavResource srcResource = getResourceFactory().createResource(request.getMemberLocator(unbindInfo.getSegment()), request, response);
+        resource.removeMember(srcResource);
+    }
+
+    /**
      * Validate the given destination resource and return the proper status
      * code: Any return value greater/equal than {@link DavServletResponse#SC_NO_CONTENT}
      * indicates an error.
@@ -617,12 +709,14 @@
      * @param request
      * @return status code indicating whether the destination is valid.
      */
-    private int validateDestination(DavResource destResource, WebdavRequest request)
+    private int validateDestination(DavResource destResource, WebdavRequest request, boolean checkHeader)
             throws DavException {
 
-        String destHeader = request.getHeader(HEADER_DESTINATION);
-        if (destHeader == null || "".equals(destHeader)) {
-            return DavServletResponse.SC_BAD_REQUEST;
+        if (checkHeader) {
+            String destHeader = request.getHeader(HEADER_DESTINATION);
+            if (destHeader == null || "".equals(destHeader)) {
+                return DavServletResponse.SC_BAD_REQUEST;
+            }
         }
         if (destResource.getLocator().equals(request.getRequestLocator())) {
             return DavServletResponse.SC_FORBIDDEN;