Start line:  
End line:  

Snippet Preview

Snippet HTML Code

Stack Overflow Questions
   /*
    * 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.catalina.servlets;
  
  
  import static org.jboss.web.CatalinaMessages.MESSAGES;
  
  import java.io.Writer;
  import java.util.Date;
  import java.util.Locale;
  import java.util.Stack;
  import java.util.Vector;
  
  
  import org.w3c.dom.Node;
Servlet which adds support for WebDAV level 2. All the basic HTTP requests are handled by the DefaultServlet. The WebDAVServlet must not be used as the default servlet (ie mapped to '/') as it will not work in this configuration. To enable WebDAV for a context add the following to web.xml:
<servlet>
<servlet-name>webdav</servlet-name>
<servlet-class>org.apache.catalina.servlets.WebdavServlet</servlet-class>
<init-param>
<param-name>debug</param-name>
<param-value>0</param-value>
</init-param>
<init-param>
<param-name>listings</param-name>
<param-value>true</param-value>
</init-param>
</servlet>
<servlet-mapping>
<servlet-name>webdav</servlet-name>
<url-pattern>/*</url-pattern>
</servlet-mapping>

This will enable read only access. To enable read-write access add:
<init-param>
<param-name>readonly</param-name>
<param-value>false</param-value>
</init-param>

To make the content editable via a different URL, using the following mapping:
<servlet-mapping>
<servlet-name>webdav</servlet-name>
<url-pattern>/webdavedit/*</url-pattern>
</servlet-mapping>

Don't forget to secure access appropriately to the editing URLs. With this configuration the context will be accessible to normal users as before. Those users with the necessary access will be able to edit content available via http://host:port/context/content using http://host:port/context/webdavedit/content

Author(s):
Remy Maucherat
Version:
$Revision: 1739 $ $Date: 2011-06-14 16:56:59 +0200 (Tue, 14 Jun 2011) $
 
 
 public class WebdavServlet
     extends DefaultServlet {
 
 
     // -------------------------------------------------------------- Constants
 
 
     private static final String METHOD_PROPFIND = "PROPFIND";
     private static final String METHOD_PROPPATCH = "PROPPATCH";
     private static final String METHOD_MKCOL = "MKCOL";
     private static final String METHOD_COPY = "COPY";
     private static final String METHOD_MOVE = "MOVE";
     private static final String METHOD_LOCK = "LOCK";
     private static final String METHOD_UNLOCK = "UNLOCK";


    
PROPFIND - Specify a property mask.
 
     private static final int FIND_BY_PROPERTY = 0;


    
PROPFIND - Display all properties.
 
     private static final int FIND_ALL_PROP = 1;


    
PROPFIND - Return property names.
 
     private static final int FIND_PROPERTY_NAMES = 2;


    
Create a new lock.
 
     private static final int LOCK_CREATION = 0;


    
Refresh lock.
 
     private static final int LOCK_REFRESH = 1;


    
Default lock timeout value.
 
     private static final int DEFAULT_TIMEOUT = 3600;


    
Maximum lock timeout.
 
     private static final int MAX_TIMEOUT = 604800;


    
Default namespace.
 
     protected static final String DEFAULT_NAMESPACE = "DAV:";


    
Simple date format for the creation date ISO representation (partial).
 
     protected static final SimpleDateFormat creationDateFormat =
         new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'");


     
MD5 message digest provider.
 
     protected static MessageDigest md5Helper;


    
The MD5 helper object for this class.
 
     protected static final MD5Encoder md5Encoder = new MD5Encoder();
 
 
 
     static {
         .setTimeZone(TimeZone.getTimeZone("GMT"));
     }
 
 
     // ----------------------------------------------------- Instance Variables
 

    
Repository of the locks put on single resources.

Key : path
Value : LockInfo

 
     private Hashtable<String,LockInforesourceLocks =
         new Hashtable<String,LockInfo>();


    
Repository of the lock-null resources.

Key : path of the collection containing the lock-null resource
Value : Vector of lock-null resource which are members of the collection. Each element of the Vector is the path associated with the lock-null resource.

 
         new Hashtable<String,Vector<String>>();


    
Vector of the heritable locks.

Key : path
Value : LockInfo

 
     private Vector<LockInfocollectionLocks = new Vector<LockInfo>();


    
Secret information used to generate reasonably secure lock ids.
 
     private String secret = "catalina";


    
Default depth in spec is infinite. Limit depth to 3 by default as infinite depth makes operations very expensive.
 
     private int maxDepth = 3;
 
 
     // --------------------------------------------------------- Public Methods
 

    
Initialize this servlet.
 
     public void init()
         throws ServletException {
 
         super.init();
 
         if (getServletConfig().getInitParameter("secret") != null)
              = getServletConfig().getInitParameter("secret");
 
         if (getServletConfig().getInitParameter("maxDepth") != null)
              = Integer.parseInt(
                     getServletConfig().getInitParameter("maxDepth"));
 
         // Load the MD5 helper used to calculate signatures.
         try {
              = MessageDigest.getInstance("MD5");
         } catch (NoSuchAlgorithmException e) {
             throw new UnavailableException("No MD5");
         }
 
     }
 
 
     // ------------------------------------------------------ Protected Methods
 

    
Return JAXP document builder instance.
 
     protected DocumentBuilder getDocumentBuilder()
         throws ServletException {
         DocumentBuilder documentBuilder = null;
         DocumentBuilderFactory documentBuilderFactory = null;
         try {
             documentBuilderFactory = DocumentBuilderFactory.newInstance();
             documentBuilderFactory.setNamespaceAware(true);
             documentBuilderFactory.setExpandEntityReferences(false);
             documentBuilder = documentBuilderFactory.newDocumentBuilder();
             documentBuilder.setEntityResolver(
                     new WebdavResolver(this.getServletContext()));
         } catch(ParserConfigurationException e) {
             throw new ServletException(.jaxpInitializationFailed());
         }
         return documentBuilder;
     }


    
Handles the special WebDAV methods.
 
     protected void service(HttpServletRequest reqHttpServletResponse resp)
         throws ServletExceptionIOException {
 
         String method = req.getMethod();
 
         if ( > 0) {
             String path = getRelativePath(req);
             log("[" + method + "] " + path);
         }
 
         if (method.equals()) {
             doPropfind(reqresp);
         } else if (method.equals()) {
             doProppatch(reqresp);
         } else if (method.equals()) {
             doMkcol(reqresp);
         } else if (method.equals()) {
             doCopy(reqresp);
         } else if (method.equals()) {
             doMove(reqresp);
         } else if (method.equals()) {
             doLock(reqresp);
         } else if (method.equals()) {
             doUnlock(reqresp);
         } else {
             // DefaultServlet processing
             super.service(reqresp);
         }
 
     }


    
Check if the conditions specified in the optional If headers are satisfied.

Parameters:
request The servlet request we are processing
response The servlet response we are creating
resourceAttributes The resource information
Returns:
boolean true if the resource meets all the specified conditions, and false if any of the conditions is not satisfied, in which case request processing is stopped
 
     protected boolean checkIfHeaders(HttpServletRequest request,
                                      HttpServletResponse response,
                                      ResourceAttributes resourceAttributes)
         throws IOException {
 
         if (!super.checkIfHeaders(requestresponseresourceAttributes))
             return false;
 
         // TODO : Checking the WebDAV If header
         return true;
 
     }


    
Override the DefaultServlet implementation and only use the PathInfo. If the ServletPath is non-null, it will be because the WebDAV servlet has been mapped to a url other than /* to configure editing at different url than normal viewing.

Parameters:
request The servlet request we are processing
 
     protected String getRelativePath(HttpServletRequest request) {
         // Are we being processed by a RequestDispatcher.include()?
         if (request.getAttribute(.) != null) {
             String result = (Stringrequest.getAttribute(
                     .);
             if ((result == null) || (result.equals("")))
                 result = "/";
             return (result);
         }
 
         // No, extract the desired path directly from the request
         String result = request.getPathInfo();
         if ((result == null) || (result.equals(""))) {
             result = "/";
         }
         return (result);
 
     }


    
OPTIONS Method.

Parameters:
req The request
resp The response
Throws:
javax.servlet.ServletException If an error occurs
java.io.IOException If an IO error occurs
 
     protected void doOptions(HttpServletRequest reqHttpServletResponse resp)
         throws ServletExceptionIOException {
 
         resp.addHeader("DAV""1,2");
 
         StringBuilder methodsAllowed = determineMethodsAllowed(,
                                                               req);
 
         resp.addHeader("Allow"methodsAllowed.toString());
         resp.addHeader("MS-Author-Via""DAV");
 
     }


    
PROPFIND Method.
 
     protected void doPropfind(HttpServletRequest reqHttpServletResponse resp)
         throws ServletExceptionIOException {
 
         if (!) {
             // Get allowed methods
             StringBuilder methodsAllowed = determineMethodsAllowed(,
                                                                   req);
 
             resp.addHeader("Allow"methodsAllowed.toString());
             resp.sendError(.);
             return;
         }
 
         String path = getRelativePath(req);
         if (path.endsWith("/"))
             path = path.substring(0, path.length() - 1);
 
         if ((path.toUpperCase(.).startsWith("/WEB-INF")) ||
             (path.toUpperCase(.).startsWith("/META-INF"))) {
             resp.sendError(.);
             return;
         }
 
         // Properties which are to be displayed.
         Vector<Stringproperties = null;
         // Propfind depth
         int depth = ;
         // Propfind type
         int type = ;
 
         String depthStr = req.getHeader("Depth");
 
         if (depthStr == null) {
             depth = ;
         } else {
             if (depthStr.equals("0")) {
                 depth = 0;
             } else if (depthStr.equals("1")) {
                 depth = 1;
             } else if (depthStr.equals("infinity")) {
                 depth = ;
             }
         }
 
         Node propNode = null;
         
         if (req.getContentLength() > 0) {
             DocumentBuilder documentBuilder = getDocumentBuilder();
     
             try {
                 Document document = documentBuilder.parse
                     (new InputSource(req.getInputStream()));
     
                 // Get the root element of the document
                 Element rootElement = document.getDocumentElement();
                 NodeList childList = rootElement.getChildNodes();
     
                 for (int i=0; i < childList.getLength(); i++) {
                     Node currentNode = childList.item(i);
                     switch (currentNode.getNodeType()) {
                     case .:
                         break;
                     case .:
                         if (currentNode.getNodeName().endsWith("prop")) {
                             type = ;
                             propNode = currentNode;
                         }
                         if (currentNode.getNodeName().endsWith("propname")) {
                             type = ;
                         }
                         if (currentNode.getNodeName().endsWith("allprop")) {
                             type = ;
                         }
                         break;
                     }
                 }
             } catch (SAXException e) {
                 // Something went wrong - bad request
                 resp.sendError(.);
             } catch (IOException e) {
                 // Something went wrong - bad request
                 resp.sendError(.);
             }
         }
 
         if (type == ) {
             properties = new Vector<String>();
             NodeList childList = propNode.getChildNodes();
 
             for (int i=0; i < childList.getLength(); i++) {
                 Node currentNode = childList.item(i);
                 switch (currentNode.getNodeType()) {
                 case .:
                     break;
                 case .:
                     String nodeName = currentNode.getNodeName();
                     String propertyName = null;
                     if (nodeName.indexOf(':') != -1) {
                         propertyName = nodeName.substring
                             (nodeName.indexOf(':') + 1);
                     } else {
                         propertyName = nodeName;
                     }
                     // href is a live property which is handled differently
                     properties.addElement(propertyName);
                     break;
                 }
             }
 
         }
 
         boolean exists = true;
         Object object = null;
         try {
             object = .lookup(path);
         } catch (NamingException e) {
             exists = false;
             int slash = path.lastIndexOf('/');
             if (slash != -1) {
                 String parentPath = path.substring(0, slash);
                 Vector<StringcurrentLockNullResources =
                     .get(parentPath);
                 if (currentLockNullResources != null) {
                     Enumeration<StringlockNullResourcesList =
                         currentLockNullResources.elements();
                     while (lockNullResourcesList.hasMoreElements()) {
                         String lockNullPath =
                             lockNullResourcesList.nextElement();
                         if (lockNullPath.equals(path)) {
                             resp.setStatus(.);
                             resp.setContentType("text/xml; charset=UTF-8");
                             // Create multistatus object
                             XMLWriter generatedXML =
                                 new XMLWriter(resp.getWriter());
                             generatedXML.writeXMLHeader();
                             generatedXML.writeElement
                                 (null"multistatus"
                                  + generateNamespaceDeclarations(),
                                  .);
                             parseLockNullProperties
                                 (reqgeneratedXMLlockNullPathtype,
                                  properties);
                             generatedXML.writeElement(null"multistatus",
                                                       .);
                             generatedXML.sendData();
                             return;
                         }
                     }
                 }
             }
         }
 
         if (!exists) {
             resp.sendError(.path);
             return;
         }
 
         resp.setStatus(.);
 
         resp.setContentType("text/xml; charset=UTF-8");
 
         // Create multistatus object
         XMLWriter generatedXML = new XMLWriter(resp.getWriter());
         generatedXML.writeXMLHeader();
 
         generatedXML.writeElement(null"multistatus"
                                   + generateNamespaceDeclarations(),
                                   .);
 
         if (depth == 0) {
             parseProperties(reqgeneratedXMLpathtype,
                             properties);
         } else {
             // The stack always contains the object of the current level
             Stack<Stringstack = new Stack<String>();
             stack.push(path);
 
             // Stack of the objects one level below
             Stack<StringstackBelow = new Stack<String>();
 
             while ((!stack.isEmpty()) && (depth >= 0)) {
 
                 String currentPath = stack.pop();
                 parseProperties(reqgeneratedXMLcurrentPath,
                                 typeproperties);
 
                 try {
                     object = .lookup(currentPath);
                 } catch (NamingException e) {
                     continue;
                 }
 
                 if ((object instanceof DirContext) && (depth > 0)) {
 
                     try {
                         NamingEnumeration<NameClassPairenumeration =
                             .list(currentPath);
                         while (enumeration.hasMoreElements()) {
                             NameClassPair ncPair = enumeration.nextElement();
                             String newPath = currentPath;
                             if (!(newPath.endsWith("/")))
                                 newPath += "/";
                             newPath += ncPair.getName();
                             stackBelow.push(newPath);
                         }
                     } catch (NamingException e) {
                         resp.sendError
                             (.,
                              path);
                         return;
                     }
 
                     // Displaying the lock-null resources present in that
                     // collection
                     String lockPath = currentPath;
                     if (lockPath.endsWith("/"))
                         lockPath =
                             lockPath.substring(0, lockPath.length() - 1);
                     Vector<StringcurrentLockNullResources =
                         .get(lockPath);
                     if (currentLockNullResources != null) {
                         Enumeration<StringlockNullResourcesList =
                             currentLockNullResources.elements();
                         while (lockNullResourcesList.hasMoreElements()) {
                             String lockNullPath =
                                 lockNullResourcesList.nextElement();
                             parseLockNullProperties
                                 (reqgeneratedXMLlockNullPathtype,
                                  properties);
                         }
                     }
 
                 }
 
                 if (stack.isEmpty()) {
                     depth--;
                     stack = stackBelow;
                     stackBelow = new Stack<String>();
                 }
 
                 generatedXML.sendData();
 
             }
         }
 
         generatedXML.writeElement(null"multistatus",
                                   .);
 
         generatedXML.sendData();
 
     }


    
PROPPATCH Method.
 
     protected void doProppatch(HttpServletRequest req,
                                HttpServletResponse resp)
         throws ServletExceptionIOException {
 
         if () {
             resp.sendError(.);
             return;
         }
 
         if (isLocked(req)) {
             resp.sendError(.);
             return;
         }
 
 
     }


    
MKCOL Method.
 
     protected void doMkcol(HttpServletRequest reqHttpServletResponse resp)
         throws ServletExceptionIOException {
 
         if () {
             resp.sendError(.);
             return;
         }
 
         if (isLocked(req)) {
             resp.sendError(.);
             return;
         }
 
         String path = getRelativePath(req);
 
         if ((path.toUpperCase(.).startsWith("/WEB-INF")) ||
             (path.toUpperCase(.).startsWith("/META-INF"))) {
             resp.sendError(.);
             return;
         }
 
         boolean exists = true;
         try {
             .lookup(path);
         } catch (NamingException e) {
             exists = false;
         }
 
         // Can't create a collection if a resource already exists at the given
         // path
         if (exists) {
             // Get allowed methods
             StringBuilder methodsAllowed = determineMethodsAllowed(,
                                                                   req);
 
             resp.addHeader("Allow"methodsAllowed.toString());
 
             resp.sendError(.);
             return;
         }
 
         if (req.getContentLength() > 0) {
             DocumentBuilder documentBuilder = getDocumentBuilder();
             try {
                 // Document document =
                 documentBuilder.parse(new InputSource(req.getInputStream()));
                 // TODO : Process this request body
                 resp.sendError(.);
                 return;
 
             } catch(SAXException saxe) {
                 // Parse error - assume invalid content
                 resp.sendError(.);
                 return;
             }
         }
 
         boolean result = true;
         try {
             .createSubcontext(path);
         } catch (NamingException e) {
             result = false;
         }
 
         if (!result) {
             resp.sendError(.,
                            WebdavStatus.getStatusText
                            (.));
         } else {
             resp.setStatus(.);
             // Removing any lock-null resource which would be present
             .remove(path);
         }
 
     }


    
DELETE Method.
 
     protected void doDelete(HttpServletRequest reqHttpServletResponse resp)
         throws ServletExceptionIOException {
 
         if () {
             resp.sendError(.);
             return;
         }
 
         if (isLocked(req)) {
             resp.sendError(.);
             return;
         }
 
         deleteResource(reqresp);
 
     }


    
Process a POST request for the specified resource.

Parameters:
req The servlet request we are processing
resp The servlet response we are creating
Throws:
java.io.IOException if an input/output error occurs
javax.servlet.ServletException if a servlet-specified error occurs
 
     protected void doPut(HttpServletRequest reqHttpServletResponse resp)
         throws ServletExceptionIOException {
 
         if (isLocked(req)) {
             resp.sendError(.);
             return;
         }
 
         super.doPut(reqresp);
 
         String path = getRelativePath(req);
 
         // Removing any lock-null resource which would be present
         .remove(path);
 
     }

    
COPY Method.
 
     protected void doCopy(HttpServletRequest reqHttpServletResponse resp)
         throws ServletExceptionIOException {
 
         if () {
             resp.sendError(.);
             return;
         }
 
         copyResource(reqresp);
 
     }


    
MOVE Method.
 
     protected void doMove(HttpServletRequest reqHttpServletResponse resp)
         throws ServletExceptionIOException {
 
         if () {
             resp.sendError(.);
             return;
         }
 
         if (isLocked(req)) {
             resp.sendError(.);
             return;
         }
 
         String path = getRelativePath(req);
 
         if (copyResource(reqresp)) {
             deleteResource(pathreqrespfalse);
         }
 
     }


    
LOCK Method.
 
     protected void doLock(HttpServletRequest reqHttpServletResponse resp)
         throws ServletExceptionIOException {
 
         if () {
             resp.sendError(.);
             return;
         }
 
         if (isLocked(req)) {
             resp.sendError(.);
             return;
         }
 
         LockInfo lock = new LockInfo();
 
         // Parsing lock request
 
         // Parsing depth header
 
         String depthStr = req.getHeader("Depth");
 
         if (depthStr == null) {
             lock.depth = ;
         } else {
             if (depthStr.equals("0")) {
                 lock.depth = 0;
             } else {
                 lock.depth = ;
             }
         }
 
         // Parsing timeout header
 
         int lockDuration = ;
         String lockDurationStr = req.getHeader("Timeout");
         if (lockDurationStr == null) {
             lockDuration = ;
         } else {
             int commaPos = lockDurationStr.indexOf(",");
             // If multiple timeouts, just use the first
             if (commaPos != -1) {
                 lockDurationStr = lockDurationStr.substring(0,commaPos);
             }
             if (lockDurationStr.startsWith("Second-")) {
                 lockDuration =
                     (new Integer(lockDurationStr.substring(7))).intValue();
             } else {
                 if (lockDurationStr.equalsIgnoreCase("infinity")) {
                     lockDuration = ;
                 } else {
                     try {
                         lockDuration =
                             (new Integer(lockDurationStr)).intValue();
                     } catch (NumberFormatException e) {
                         lockDuration = ;
                     }
                 }
             }
             if (lockDuration == 0) {
                 lockDuration = ;
             }
             if (lockDuration > ) {
                 lockDuration = ;
             }
         }
         lock.expiresAt = System.currentTimeMillis() + (lockDuration * 1000);
 
         int lockRequestType = ;
 
         Node lockInfoNode = null;
 
         DocumentBuilder documentBuilder = getDocumentBuilder();
 
         try {
             Document document = documentBuilder.parse(new InputSource
                 (req.getInputStream()));
 
             // Get the root element of the document
             Element rootElement = document.getDocumentElement();
             lockInfoNode = rootElement;
         } catch (IOException e) {
             lockRequestType = ;
         } catch (SAXException e) {
             lockRequestType = ;
         }
 
         if (lockInfoNode != null) {
 
             // Reading lock information
 
             NodeList childList = lockInfoNode.getChildNodes();
             StringWriter strWriter = null;
             DOMWriter domWriter = null;
 
             Node lockScopeNode = null;
             Node lockTypeNode = null;
             Node lockOwnerNode = null;
 
             for (int i=0; i < childList.getLength(); i++) {
                 Node currentNode = childList.item(i);
                 switch (currentNode.getNodeType()) {
                 case .:
                     break;
                 case .:
                     String nodeName = currentNode.getNodeName();
                     if (nodeName.endsWith("lockscope")) {
                         lockScopeNode = currentNode;
                     }
                     if (nodeName.endsWith("locktype")) {
                         lockTypeNode = currentNode;
                     }
                     if (nodeName.endsWith("owner")) {
                         lockOwnerNode = currentNode;
                     }
                     break;
                 }
             }
 
             if (lockScopeNode != null) {
 
                 childList = lockScopeNode.getChildNodes();
                 for (int i=0; i < childList.getLength(); i++) {
                     Node currentNode = childList.item(i);
                     switch (currentNode.getNodeType()) {
                     case .:
                         break;
                     case .:
                         String tempScope = currentNode.getNodeName();
                         if (tempScope.indexOf(':') != -1) {
                             lock.scope = tempScope.substring
                                 (tempScope.indexOf(':') + 1);
                        } else {
                            lock.scope = tempScope;
                        }
                        break;
                    }
                }
                if (lock.scope == null) {
                    // Bad request
                    resp.setStatus(.);
                }
            } else {
                // Bad request
                resp.setStatus(.);
            }
            if (lockTypeNode != null) {
                childList = lockTypeNode.getChildNodes();
                for (int i=0; i < childList.getLength(); i++) {
                    Node currentNode = childList.item(i);
                    switch (currentNode.getNodeType()) {
                    case .:
                        break;
                    case .:
                        String tempType = currentNode.getNodeName();
                        if (tempType.indexOf(':') != -1) {
                            lock.type =
                                tempType.substring(tempType.indexOf(':') + 1);
                        } else {
                            lock.type = tempType;
                        }
                        break;
                    }
                }
                if (lock.type == null) {
                    // Bad request
                    resp.setStatus(.);
                }
            } else {
                // Bad request
                resp.setStatus(.);
            }
            if (lockOwnerNode != null) {
                childList = lockOwnerNode.getChildNodes();
                for (int i=0; i < childList.getLength(); i++) {
                    Node currentNode = childList.item(i);
                    switch (currentNode.getNodeType()) {
                    case .:
                        lock.owner += currentNode.getNodeValue();
                        break;
                    case .:
                        strWriter = new StringWriter();
                        domWriter = new DOMWriter(strWritertrue);
                        domWriter.setQualifiedNames(false);
                        domWriter.print(currentNode);
                        lock.owner += strWriter.toString();
                        break;
                    }
                }
                if (lock.owner == null) {
                    // Bad request
                    resp.setStatus(.);
                }
            } else {
                lock.owner = new String();
            }
        }
        String path = getRelativePath(req);
        lock.path = path;
        boolean exists = true;
        Object object = null;
        try {
            object = .lookup(path);
        } catch (NamingException e) {
            exists = false;
        }
        Enumeration<LockInfolocksList = null;
        if (lockRequestType == ) {
            // Generating lock id
            String lockTokenStr = req.getServletPath() + "-" + lock.type + "-"
                + lock.scope + "-" + req.getUserPrincipal() + "-"
                + lock.depth + "-" + lock.owner + "-" + lock.tokens + "-"
                + lock.expiresAt + "-" + System.currentTimeMillis() + "-"
                + ;
            String lockToken =
                .encode(.digest(lockTokenStr.getBytes()));
            if ( (exists) && (object instanceof DirContext) &&
                 (lock.depth == ) ) {
                // Locking a collection (and all its member resources)
                // Checking if a child resource of this collection is
                // already locked
                Vector<StringlockPaths = new Vector<String>();
                locksList = .elements();
                while (locksList.hasMoreElements()) {
                    LockInfo currentLock = locksList.nextElement();
                    if (currentLock.hasExpired()) {
                        .remove(currentLock.path);
                        continue;
                    }
                    if ( (currentLock.path.startsWith(lock.path)) &&
                         ((currentLock.isExclusive()) ||
                          (lock.isExclusive())) ) {
                        // A child collection of this collection is locked
                        lockPaths.addElement(currentLock.path);
                    }
                }
                locksList = .elements();
                while (locksList.hasMoreElements()) {
                    LockInfo currentLock = locksList.nextElement();
                    if (currentLock.hasExpired()) {
                        .remove(currentLock.path);
                        continue;
                    }
                    if ( (currentLock.path.startsWith(lock.path)) &&
                         ((currentLock.isExclusive()) ||
                          (lock.isExclusive())) ) {
                        // A child resource of this collection is locked
                        lockPaths.addElement(currentLock.path);
                    }
                }
                if (!lockPaths.isEmpty()) {
                    // One of the child paths was locked
                    // We generate a multistatus error report
                    Enumeration<StringlockPathsList = lockPaths.elements();
                    resp.setStatus(.);
                    XMLWriter generatedXML = new XMLWriter();
                    generatedXML.writeXMLHeader();
                    generatedXML.writeElement
                        (null"multistatus" + generateNamespaceDeclarations(),
                         .);
                    while (lockPathsList.hasMoreElements()) {
                        generatedXML.writeElement(null"response",
                                                  .);
                        generatedXML.writeElement(null"href",
                                                  .);
                        generatedXML
                            .writeText(lockPathsList.nextElement());
                        generatedXML.writeElement(null"href",
                                                  .);
                        generatedXML.writeElement(null"status",
                                                  .);
                        generatedXML
                            .writeText("HTTP/1.1 " + .
                                       + " " + WebdavStatus
                                       .getStatusText(.));
                        generatedXML.writeElement(null"status",
                                                  .);
                        generatedXML.writeElement(null"response",
                                                  .);
                    }
                    generatedXML.writeElement(null"multistatus",
                                          .);
                    Writer writer = resp.getWriter();
                    writer.write(generatedXML.toString());
                    writer.close();
                    return;
                }
                boolean addLock = true;
                // Checking if there is already a shared lock on this path
                locksList = .elements();
                while (locksList.hasMoreElements()) {
                    LockInfo currentLock = locksList.nextElement();
                    if (currentLock.path.equals(lock.path)) {
                        if (currentLock.isExclusive()) {
                            resp.sendError(.);
                            return;
                        } else {
                            if (lock.isExclusive()) {
                                resp.sendError(.);
                                return;
                            }
                        }
                        currentLock.tokens.addElement(lockToken);
                        lock = currentLock;
                        addLock = false;
                    }
                }
                if (addLock) {
                    lock.tokens.addElement(lockToken);
                    .addElement(lock);
                }
            } else {
                // Locking a single resource
                // Retrieving an already existing lock on that resource
                LockInfo presentLock = .get(lock.path);
                if (presentLock != null) {
                    if ((presentLock.isExclusive()) || (lock.isExclusive())) {
                        // If either lock is exclusive, the lock can't be
                        // granted
                        resp.sendError(.);
                        return;
                    } else {
                        presentLock.tokens.addElement(lockToken);
                        lock = presentLock;
                    }
                } else {
                    lock.tokens.addElement(lockToken);
                    .put(lock.