tomcat-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From cos...@apache.org
Subject svn commit: r534293 [7/11] - in /tomcat/sandbox/tomcat-lite: ./ bin/ external/ java/ java/org/apache/commons/logging/ java/org/apache/tomcat/lite/ java/org/apache/tomcat/lite/ctxmap/ java/org/apache/tomcat/lite/http/ java/org/apache/tomcat/lite/http11/...
Date Wed, 02 May 2007 02:22:50 GMT
Added: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/Webdav2Servlet.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/Webdav2Servlet.java?view=auto&rev=534293
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/Webdav2Servlet.java (added)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/Webdav2Servlet.java Tue May  1 19:22:45 2007
@@ -0,0 +1,2026 @@
+/*
+ * Copyright 1999,2004 The Apache Software Foundation.
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+
+package org.apache.tomcat.servlets.file;
+
+
+import java.io.File;
+import java.io.IOException;
+import java.io.PrintWriter;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.security.MessageDigest;
+import java.security.NoSuchAlgorithmException;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Stack;
+import java.util.Vector;
+
+import javax.servlet.ServletException;
+import javax.servlet.UnavailableException;
+import javax.servlet.http.HttpServletRequest;
+import javax.servlet.http.HttpServletResponse;
+import javax.xml.parsers.DocumentBuilder;
+
+import org.apache.tomcat.servlets.util.UrlUtils;
+import org.apache.tomcat.util.http.FastHttpDateFormat;
+import org.w3c.dom.Attr;
+import org.w3c.dom.Document;
+import org.w3c.dom.Element;
+import org.w3c.dom.NamedNodeMap;
+import org.w3c.dom.Node;
+import org.w3c.dom.NodeList;
+import org.xml.sax.InputSource;
+
+
+
+/**
+ * Servlet which adds support for WebDAV level 2. All the basic HTTP requests
+ * are handled by the DefaultServlet.
+ *
+ * @author Remy Maucherat
+ * @version $Revision: 303599 $ $Date: 2004-12-20 19:54:14 +0100 (lun., 20 déc. 2004) $
+ */
+
+public class Webdav2Servlet extends WebdavServlet {
+
+    /**
+     * Create a new lock.
+     */
+    private static final int LOCK_CREATION = 0;
+
+
+    /**
+     * Refresh lock.
+     */
+    private static final int LOCK_REFRESH = 1;
+
+    /**
+     * Default lock timeout value.
+     */
+    protected static final int DEFAULT_TIMEOUT = 3600;
+
+
+    /**
+     * Maximum lock timeout.
+     */
+    protected static final int MAX_TIMEOUT = 604800;
+
+    /**
+     * MD5 message digest provider.
+     */
+    protected static MessageDigest md5Helper;
+
+
+    /**
+     * Repository of the locks put on single resources.
+     * <p>
+     * Key : path <br>
+     * Value : LockInfo
+     */
+    protected Hashtable resourceLocks = new Hashtable();
+
+
+    /**
+     * Vector of the heritable locks.
+     * <p>
+     * Key : path <br>
+     * Value : LockInfo
+     */
+    protected Vector collectionLocks = new Vector();
+
+
+    /**
+     * The MD5 helper object for this class.
+     */
+    protected static final MD5Encoder md5Encoder = new MD5Encoder();
+
+
+    /**
+     * Secret information used to generate reasonably secure lock ids.
+     */
+    protected String secret = "catalina";
+
+
+    public void init() throws ServletException {
+        super.init();
+        
+        String value = null;
+        try {
+            value = getServletConfig().getInitParameter("secret");
+            if (value != null)
+                secret = value;
+        } catch (Throwable t) {
+            ;
+        }
+
+        // Load the MD5 helper used to calculate signatures.
+        try {
+            md5Helper = MessageDigest.getInstance("MD5");
+        } catch (NoSuchAlgorithmException e) {
+            throw new UnavailableException("No MD5");
+        }
+
+    }
+
+    /**
+     * OPTIONS Method - return DAV 1,2
+     *
+     * @param req The request
+     * @param resp The response
+     * @throws ServletException If an error occurs
+     * @throws IOException If an IO error occurs
+     */
+    protected void doOptions(HttpServletRequest req, HttpServletResponse resp)
+        throws ServletException, IOException {
+
+        resp.addHeader("DAV", "1.2"); 
+
+        StringBuffer methodsAllowed = determineMethodsAllowed(basePath, req);
+
+        resp.addHeader("Allow", methodsAllowed.toString());
+        resp.addHeader("MS-Author-Via", "DAV");
+
+    }
+
+    /**
+     * Determines the methods normally allowed for the resource.
+     *
+     */
+    protected StringBuffer determineMethodsAllowed(File basePath,
+                                                   HttpServletRequest req) {
+
+        StringBuffer methodsAllowed = new StringBuffer();
+        
+        String path = getRelativePath(req);
+
+        File object = new File(basePath, path);
+
+        if (!object.exists()) {
+            methodsAllowed.append("OPTIONS, MKCOL, PUT, LOCK");
+            return methodsAllowed;
+        }
+
+        methodsAllowed.append("OPTIONS, GET, HEAD, POST, DELETE, TRACE");
+        methodsAllowed.append(", PROPPATCH, COPY, MOVE, LOCK, UNLOCK");
+        methodsAllowed.append(", PROPFIND");
+
+        if (object.isDirectory()) {
+            methodsAllowed.append(", PUT");
+        }
+
+        return methodsAllowed;
+    }
+
+
+    /**
+     * PROPFIND Method.
+     */
+    protected void doPropfind(HttpServletRequest req, HttpServletResponse resp)
+        throws ServletException, IOException {
+
+        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(WebdavStatus.SC_FORBIDDEN);
+            return;
+        }
+
+        // Properties which are to be displayed.
+        Vector properties = null;
+        // Propfind depth
+        int depth = INFINITY;
+        // Propfind type
+        int type = FIND_ALL_PROP;
+
+        String depthStr = req.getHeader("Depth");
+
+        if (depthStr == null) {
+            depth = INFINITY;
+        } else {
+            if (depthStr.equals("0")) {
+                depth = 0;
+            } else if (depthStr.equals("1")) {
+                depth = 1;
+            } else if (depthStr.equals("infinity")) {
+                depth = INFINITY;
+            }
+        }
+
+        Node propNode = null;
+
+        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 Node.TEXT_NODE:
+                    break;
+                case Node.ELEMENT_NODE:
+                    if (currentNode.getNodeName().endsWith("prop")) {
+                        type = FIND_BY_PROPERTY;
+                        propNode = currentNode;
+                    }
+                    if (currentNode.getNodeName().endsWith("propname")) {
+                        type = FIND_PROPERTY_NAMES;
+                    }
+                    if (currentNode.getNodeName().endsWith("allprop")) {
+                        type = FIND_ALL_PROP;
+                    }
+                    break;
+                }
+            }
+        } catch(Exception e) {
+            // Most likely there was no content : we use the defaults.
+            // TODO : Enhance that !
+        }
+
+        if (type == FIND_BY_PROPERTY) {
+            properties = new Vector();
+            NodeList childList = propNode.getChildNodes();
+
+            for (int i=0; i < childList.getLength(); i++) {
+                Node currentNode = childList.item(i);
+                switch (currentNode.getNodeType()) {
+                case Node.TEXT_NODE:
+                    break;
+                case Node.ELEMENT_NODE:
+                    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;
+        File object = new File(basePath, path);
+        if (!object.exists()) {
+            exists = false;
+            int slash = path.lastIndexOf('/');
+            if (slash != -1) {
+                String parentPath = path.substring(0, slash);
+                Vector currentLockNullResources =
+                    (Vector) lockNullResources.get(parentPath);
+                if (currentLockNullResources != null) {
+                    Enumeration lockNullResourcesList =
+                        currentLockNullResources.elements();
+                    while (lockNullResourcesList.hasMoreElements()) {
+                        String lockNullPath = (String)
+                            lockNullResourcesList.nextElement();
+                        if (lockNullPath.equals(path)) {
+                            resp.setStatus(WebdavStatus.SC_MULTI_STATUS);
+                            resp.setContentType("text/xml; charset=UTF-8");
+                            // Create multistatus object
+                            XMLWriter generatedXML =
+                                new XMLWriter(resp.getWriter());
+                            generatedXML.writeXMLHeader();
+                            generatedXML.writeElement
+                                (null, "multistatus"
+                                 + generateNamespaceDeclarations(),
+                                 XMLWriter.OPENING);
+                            parseLockNullProperties
+                                (req, generatedXML, lockNullPath, type,
+                                 properties);
+                            generatedXML.writeElement(null, "multistatus",
+                                                      XMLWriter.CLOSING);
+                            generatedXML.sendData();
+                            return;
+                        }
+                    }
+                }
+            }
+        }
+
+        if (!exists) {
+            resp.sendError(HttpServletResponse.SC_NOT_FOUND, path);
+            return;
+        }
+
+        resp.setStatus(WebdavStatus.SC_MULTI_STATUS);
+
+        resp.setContentType("text/xml; charset=UTF-8");
+
+        // Create multistatus object
+        XMLWriter generatedXML = new XMLWriter(resp.getWriter());
+        generatedXML.writeXMLHeader();
+
+        generatedXML.writeElement(null, "multistatus"
+                                  + generateNamespaceDeclarations(),
+                                  XMLWriter.OPENING);
+
+        if (depth == 0) {
+            parseProperties(req, generatedXML, path, type,
+                            properties);
+        } else {
+            // The stack always contains the object of the current level
+            Stack stack = new Stack();
+            stack.push(path);
+
+            // Stack of the objects one level below
+            Stack stackBelow = new Stack();
+
+            while ((!stack.isEmpty()) && (depth >= 0)) {
+
+                String currentPath = (String) stack.pop();
+                parseProperties(req, generatedXML, currentPath,
+                                type, properties);
+
+                object = new File(basePath,currentPath);
+                if (!object.exists()) {
+                    continue;
+                }
+
+                if ((object.isDirectory()) && (depth > 0)) {
+
+                    File[] files = object.listFiles();
+                    for (int i=0; i < files.length; i++) {
+                        String newPath = currentPath;
+                        if (!(newPath.endsWith("/")))
+                            newPath += "/";
+                        newPath += files[i].getName();
+                        stackBelow.push(newPath);
+                    }
+
+                    // Displaying the lock-null resources present in that
+                    // collection
+                    String lockPath = currentPath;
+                    if (lockPath.endsWith("/"))
+                        lockPath =
+                            lockPath.substring(0, lockPath.length() - 1);
+                    Vector currentLockNullResources =
+                        (Vector) lockNullResources.get(lockPath);
+                    if (currentLockNullResources != null) {
+                        Enumeration lockNullResourcesList =
+                            currentLockNullResources.elements();
+                        while (lockNullResourcesList.hasMoreElements()) {
+                            String lockNullPath = (String)
+                                lockNullResourcesList.nextElement();
+                            parseLockNullProperties
+                                (req, generatedXML, lockNullPath, type,
+                                 properties);
+                        }
+                    }
+
+                }
+
+                if (stack.isEmpty()) {
+                    depth--;
+                    stack = stackBelow;
+                    stackBelow = new Stack();
+                }
+
+                generatedXML.sendData();
+
+            }
+        }
+
+        generatedXML.writeElement(null, "multistatus",
+                                  XMLWriter.CLOSING);
+
+        generatedXML.sendData();
+
+    }
+
+
+
+    /**
+     * LOCK Method.
+     */
+    protected void doLock(HttpServletRequest req, HttpServletResponse resp)
+        throws ServletException, IOException {
+
+        resp.sendError(WebdavStatus.SC_NOT_IMPLEMENTED);
+        if (readOnly) {
+            resp.sendError(WebdavStatus.SC_FORBIDDEN);
+            return;
+        }
+
+        if (isLocked(req)) {
+            resp.sendError(WebdavStatus.SC_LOCKED);
+            return;
+        }
+
+        LockInfo lock = new LockInfo();
+
+        // Parsing lock request
+
+        // Parsing depth header
+
+        String depthStr = req.getHeader("Depth");
+        if (depthStr == null) {
+            lock.depth = INFINITY;
+        } else {
+            if (depthStr.equals("0")) {
+                lock.depth = 0;
+            } else {
+                lock.depth = INFINITY;
+            }
+        }
+
+        // Parsing timeout header
+        int lockDuration = getLockDuration(req);
+        lock.expiresAt = System.currentTimeMillis() + (lockDuration * 1000);
+
+        int lockRequestType = LOCK_CREATION;
+
+        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(Exception e) {
+            lockRequestType = LOCK_REFRESH;
+        }
+
+        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 Node.TEXT_NODE:
+                    break;
+                case Node.ELEMENT_NODE:
+                    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 Node.TEXT_NODE:
+                        break;
+                    case Node.ELEMENT_NODE:
+                        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(WebdavStatus.SC_BAD_REQUEST);
+                }
+
+            } else {
+                // Bad request
+                resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
+            }
+
+            if (lockTypeNode != null) {
+                childList = lockTypeNode.getChildNodes();
+                for (int i=0; i < childList.getLength(); i++) {
+                    Node currentNode = childList.item(i);
+                    switch (currentNode.getNodeType()) {
+                    case Node.TEXT_NODE:
+                        break;
+                    case Node.ELEMENT_NODE:
+                        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(WebdavStatus.SC_BAD_REQUEST);
+                }
+            } else {
+                // Bad request
+                resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
+            }
+
+            if (lockOwnerNode != null) {
+                childList = lockOwnerNode.getChildNodes();
+                for (int i=0; i < childList.getLength(); i++) {
+                    Node currentNode = childList.item(i);
+                    switch (currentNode.getNodeType()) {
+                    case Node.TEXT_NODE:
+                        lock.owner += currentNode.getNodeValue();
+                        break;
+                    case Node.ELEMENT_NODE:
+                        // OWNER: ANY
+                        strWriter = new StringWriter();
+                        domWriter = new DOMWriter(strWriter, true);
+                        domWriter.setQualifiedNames(false);
+                        domWriter.print(currentNode);
+                        lock.owner += strWriter.toString();
+                        break;
+                    }
+                }
+
+                if (lock.owner == null) {
+                    // Bad request
+                    resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
+                }
+            } else {
+                lock.owner = new String();
+            }
+
+        }
+
+        String path = getRelativePath(req);
+
+        lock.path = path;
+
+        boolean exists = true;
+        File object = null;
+            object = new File(basePath,path);
+        if (!object.exists()) {
+            exists = false;
+        }
+
+        Enumeration locksList = null;
+
+        if (lockRequestType == LOCK_CREATION) {
+
+            // Generating lock id
+            String lockTokenStr = req.getServletPath() + "-" + lock.type + "-"
+                + lock.scope + "-" + req.getUserPrincipal() + "-"
+                + lock.depth + "-" + lock.owner + "-" + lock.tokens + "-"
+                + lock.expiresAt + "-" + System.currentTimeMillis() + "-"
+                + secret;
+            String lockToken =
+                md5Encoder.encode(md5Helper.digest(lockTokenStr.getBytes()));
+
+            if ( (exists) && (object.isDirectory()) &&
+                 (lock.depth == INFINITY) ) {
+
+                // Locking a collection (and all its member resources)
+
+                // Checking if a child resource of this collection is
+                // already locked
+                Vector lockPaths = new Vector();
+                locksList = collectionLocks.elements();
+                while (locksList.hasMoreElements()) {
+                    LockInfo currentLock = (LockInfo) locksList.nextElement();
+                    if (currentLock.hasExpired()) {
+                        resourceLocks.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 = resourceLocks.elements();
+                while (locksList.hasMoreElements()) {
+                    LockInfo currentLock = (LockInfo) locksList.nextElement();
+                    if (currentLock.hasExpired()) {
+                        resourceLocks.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 lockPathsList = lockPaths.elements();
+
+                    resp.setStatus(WebdavStatus.SC_CONFLICT);
+
+                    XMLWriter generatedXML = new XMLWriter();
+                    generatedXML.writeXMLHeader();
+
+                    generatedXML.writeElement
+                        (null, "multistatus" + generateNamespaceDeclarations(),
+                         XMLWriter.OPENING);
+
+                    while (lockPathsList.hasMoreElements()) {
+                        generatedXML.writeElement(null, "response",
+                                                  XMLWriter.OPENING);
+                        generatedXML.writeElement(null, "href",
+                                                  XMLWriter.OPENING);
+                        generatedXML
+                            .writeText((String) lockPathsList.nextElement());
+                        generatedXML.writeElement(null, "href",
+                                                  XMLWriter.CLOSING);
+                        generatedXML.writeElement(null, "status",
+                                                  XMLWriter.OPENING);
+                        generatedXML
+                            .writeText("HTTP/1.1 " + WebdavStatus.SC_LOCKED
+                                       + " " + WebdavStatus
+                                       .getStatusText(WebdavStatus.SC_LOCKED));
+                        generatedXML.writeElement(null, "status",
+                                                  XMLWriter.CLOSING);
+
+                        generatedXML.writeElement(null, "response",
+                                                  XMLWriter.CLOSING);
+                    }
+
+                    generatedXML.writeElement(null, "multistatus",
+                                          XMLWriter.CLOSING);
+
+                    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 = collectionLocks.elements();
+                while (locksList.hasMoreElements()) {
+
+                    LockInfo currentLock = (LockInfo) locksList.nextElement();
+                    if (currentLock.path.equals(lock.path)) {
+
+                        if (currentLock.isExclusive()) {
+                            resp.sendError(WebdavStatus.SC_LOCKED);
+                            return;
+                        } else {
+                            if (lock.isExclusive()) {
+                                resp.sendError(WebdavStatus.SC_LOCKED);
+                                return;
+                            }
+                        }
+
+                        currentLock.tokens.addElement(lockToken);
+                        lock = currentLock;
+                        addLock = false;
+
+                    }
+
+                }
+
+                if (addLock) {
+                    lock.tokens.addElement(lockToken);
+                    collectionLocks.addElement(lock);
+                }
+
+            } else {
+
+                // Locking a single resource
+
+                // Retrieving an already existing lock on that resource
+                LockInfo presentLock = (LockInfo) resourceLocks.get(lock.path);
+                if (presentLock != null) {
+
+                    if ((presentLock.isExclusive()) || (lock.isExclusive())) {
+                        // If either lock is exclusive, the lock can't be
+                        // granted
+                        resp.sendError(WebdavStatus.SC_PRECONDITION_FAILED);
+                        return;
+                    } else {
+                        presentLock.tokens.addElement(lockToken);
+                        lock = presentLock;
+                    }
+
+                } else {
+
+                    lock.tokens.addElement(lockToken);
+                    resourceLocks.put(lock.path, lock);
+
+                    // Checking if a resource exists at this path
+                    exists = true;
+                        object = new File(basePath,path);
+                    if (!object.exists()) {
+                        exists = false;
+                    }
+                    if (!exists) {
+
+                        // "Creating" a lock-null resource
+                        int slash = lock.path.lastIndexOf('/');
+                        String parentPath = lock.path.substring(0, slash);
+
+                        Vector lockNulls =
+                            (Vector) lockNullResources.get(parentPath);
+                        if (lockNulls == null) {
+                            lockNulls = new Vector();
+                            lockNullResources.put(parentPath, lockNulls);
+                        }
+
+                        lockNulls.addElement(lock.path);
+
+                    }
+                    // Add the Lock-Token header as by RFC 2518 8.10.1
+                    // - only do this for newly created locks
+                    resp.addHeader("Lock-Token", "<opaquelocktoken:"
+                                   + lockToken + ">");
+                }
+
+            }
+
+        }
+
+        if (lockRequestType == LOCK_REFRESH) {
+
+            String ifHeader = req.getHeader("If");
+            if (ifHeader == null)
+                ifHeader = "";
+
+            // Checking resource locks
+
+            LockInfo toRenew = (LockInfo) resourceLocks.get(path);
+            Enumeration tokenList = null;
+            if (lock != null) {
+
+                // At least one of the tokens of the locks must have been given
+
+                tokenList = toRenew.tokens.elements();
+                while (tokenList.hasMoreElements()) {
+                    String token = (String) tokenList.nextElement();
+                    if (ifHeader.indexOf(token) != -1) {
+                        toRenew.expiresAt = lock.expiresAt;
+                        lock = toRenew;
+                    }
+                }
+
+            }
+
+            // Checking inheritable collection locks
+
+            Enumeration collectionLocksList = collectionLocks.elements();
+            while (collectionLocksList.hasMoreElements()) {
+                toRenew = (LockInfo) collectionLocksList.nextElement();
+                if (path.equals(toRenew.path)) {
+
+                    tokenList = toRenew.tokens.elements();
+                    while (tokenList.hasMoreElements()) {
+                        String token = (String) tokenList.nextElement();
+                        if (ifHeader.indexOf(token) != -1) {
+                            toRenew.expiresAt = lock.expiresAt;
+                            lock = toRenew;
+                        }
+                    }
+
+                }
+            }
+
+        }
+
+        // Set the status, then generate the XML response containing
+        // the lock information
+        XMLWriter generatedXML = new XMLWriter();
+        generatedXML.writeXMLHeader();
+        generatedXML.writeElement(null, "prop"
+                                  + generateNamespaceDeclarations(),
+                                  XMLWriter.OPENING);
+
+        generatedXML.writeElement(null, "lockdiscovery",
+                                  XMLWriter.OPENING);
+
+        lock.toXML(generatedXML);
+
+        generatedXML.writeElement(null, "lockdiscovery",
+                                  XMLWriter.CLOSING);
+
+        generatedXML.writeElement(null, "prop", XMLWriter.CLOSING);
+
+        resp.setStatus(WebdavStatus.SC_OK);
+        resp.setContentType("text/xml; charset=UTF-8");
+        Writer writer = resp.getWriter();
+        writer.write(generatedXML.toString());
+        writer.close();
+
+    }
+
+
+    private int getLockDuration(HttpServletRequest req) {
+        int lockDuration = DEFAULT_TIMEOUT;
+        String lockDurationStr = req.getHeader("Timeout");
+        if (lockDurationStr == null) {
+            lockDuration = DEFAULT_TIMEOUT;
+        } 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 = MAX_TIMEOUT;
+                } else {
+                    try {
+                        lockDuration =
+                            (new Integer(lockDurationStr)).intValue();
+                    } catch (NumberFormatException e) {
+                        lockDuration = MAX_TIMEOUT;
+                    }
+                }
+            }
+            if (lockDuration == 0) {
+                lockDuration = DEFAULT_TIMEOUT;
+            }
+            if (lockDuration > MAX_TIMEOUT) {
+                lockDuration = MAX_TIMEOUT;
+            }
+        }
+        return lockDuration;
+    }
+
+
+    /**
+     * UNLOCK Method.
+     */
+    protected void doUnlock(HttpServletRequest req, HttpServletResponse resp)
+        throws ServletException, IOException {
+
+        resp.sendError(WebdavStatus.SC_NOT_IMPLEMENTED);
+
+        if (readOnly) {
+            resp.sendError(WebdavStatus.SC_FORBIDDEN);
+            return;
+        }
+
+        if (isLocked(req)) {
+            resp.sendError(WebdavStatus.SC_LOCKED);
+            return;
+        }
+
+        String path = getRelativePath(req);
+
+        String lockTokenHeader = req.getHeader("Lock-Token");
+        if (lockTokenHeader == null)
+            lockTokenHeader = "";
+
+        // Checking resource locks
+
+        LockInfo lock = (LockInfo) resourceLocks.get(path);
+        Enumeration tokenList = null;
+        if (lock != null) {
+
+            // At least one of the tokens of the locks must have been given
+
+            tokenList = lock.tokens.elements();
+            while (tokenList.hasMoreElements()) {
+                String token = (String) tokenList.nextElement();
+                if (lockTokenHeader.indexOf(token) != -1) {
+                    lock.tokens.removeElement(token);
+                }
+            }
+
+            if (lock.tokens.isEmpty()) {
+                resourceLocks.remove(path);
+                // Removing any lock-null resource which would be present
+                lockNullResources.remove(path);
+            }
+
+        }
+
+        // Checking inheritable collection locks
+
+        Enumeration collectionLocksList = collectionLocks.elements();
+        while (collectionLocksList.hasMoreElements()) {
+            lock = (LockInfo) collectionLocksList.nextElement();
+            if (path.equals(lock.path)) {
+
+                tokenList = lock.tokens.elements();
+                while (tokenList.hasMoreElements()) {
+                    String token = (String) tokenList.nextElement();
+                    if (lockTokenHeader.indexOf(token) != -1) {
+                        lock.tokens.removeElement(token);
+                        break;
+                    }
+                }
+
+                if (lock.tokens.isEmpty()) {
+                    collectionLocks.removeElement(lock);
+                    // Removing any lock-null resource which would be present
+                    lockNullResources.remove(path);
+                }
+
+            }
+        }
+
+        resp.setStatus(WebdavStatus.SC_NO_CONTENT);
+
+    }
+
+
+    /**
+     * Check to see if a resource is currently write locked. The method
+     * will look at the "If" header to make sure the client
+     * has give the appropriate lock tokens.
+     *
+     * @param req Servlet request
+     * @return boolean true if the resource is locked (and no appropriate
+     * lock token has been found for at least one of the non-shared locks which
+     * are present on the resource).
+     */
+    protected boolean isLocked(HttpServletRequest req) {
+
+        String path = getRelativePath(req);
+
+        String ifHeader = req.getHeader("If");
+        if (ifHeader == null)
+            ifHeader = "";
+
+        String lockTokenHeader = req.getHeader("Lock-Token");
+        if (lockTokenHeader == null)
+            lockTokenHeader = "";
+
+        return isLocked(path, ifHeader + lockTokenHeader);
+
+    }
+
+
+    /**
+     * Check to see if a resource is currently write locked.
+     *
+     * @param path Path of the resource
+     * @param ifHeader "If" HTTP header which was included in the request
+     * @return boolean true if the resource is locked (and no appropriate
+     * lock token has been found for at least one of the non-shared locks which
+     * are present on the resource).
+     */
+    protected boolean isLocked(String path, String ifHeader) {
+
+        // Checking resource locks
+
+        LockInfo lock = (LockInfo) resourceLocks.get(path);
+        Enumeration tokenList = null;
+        if ((lock != null) && (lock.hasExpired())) {
+            resourceLocks.remove(path);
+        } else if (lock != null) {
+
+            // At least one of the tokens of the locks must have been given
+
+            tokenList = lock.tokens.elements();
+            boolean tokenMatch = false;
+            while (tokenList.hasMoreElements()) {
+                String token = (String) tokenList.nextElement();
+                if (ifHeader.indexOf(token) != -1)
+                    tokenMatch = true;
+            }
+            if (!tokenMatch)
+                return true;
+
+        }
+
+        // Checking inheritable collection locks
+
+        Enumeration collectionLocksList = collectionLocks.elements();
+        while (collectionLocksList.hasMoreElements()) {
+            lock = (LockInfo) collectionLocksList.nextElement();
+            if (lock.hasExpired()) {
+                collectionLocks.removeElement(lock);
+            } else if (path.startsWith(lock.path)) {
+
+                tokenList = lock.tokens.elements();
+                boolean tokenMatch = false;
+                while (tokenList.hasMoreElements()) {
+                    String token = (String) tokenList.nextElement();
+                    if (ifHeader.indexOf(token) != -1)
+                        tokenMatch = true;
+                }
+                if (!tokenMatch)
+                    return true;
+
+            }
+        }
+
+        return false;
+
+    }
+
+    /**
+     * Propfind helper method.
+     *
+     * @param req The servlet request
+     * @param resources Resources object associated with this context
+     * @param generatedXML XML response to the Propfind request
+     * @param path Path of the current resource
+     * @param type Propfind type
+     * @param propertiesVector If the propfind type is find properties by
+     * name, then this Vector contains those properties
+     */
+    protected void parseProperties(HttpServletRequest req,
+                                   XMLWriter generatedXML,
+                                   String path, int type,
+                                   Vector propertiesVector) {
+
+        // Exclude any resource in the /WEB-INF and /META-INF subdirectories
+        // (the "toUpperCase()" avoids problems on Windows systems)
+        if (path.toUpperCase().startsWith("/WEB-INF") ||
+            path.toUpperCase().startsWith("/META-INF"))
+            return;
+
+        File cacheEntry = new File(basePath, path);
+
+        generatedXML.writeElement(null, "response", XMLWriter.OPENING);
+        String status = new String("HTTP/1.1 " + WebdavStatus.SC_OK + " "
+                                   + WebdavStatus.getStatusText
+                                   (WebdavStatus.SC_OK));
+
+        // Generating href element
+        generatedXML.writeElement(null, "href", XMLWriter.OPENING);
+
+        String href = req.getContextPath();// + req.getServletPath() + 
+        //  req.getPathInfo();
+        
+        // ??? 
+        if ((href.endsWith("/")) && (path.startsWith("/")))
+            href += path.substring(1);
+        else
+            href += path;
+        if ((cacheEntry.isDirectory()) && (!href.endsWith("/")))
+            href += "/";
+
+        generatedXML.writeText(rewriteUrl(href));
+
+        generatedXML.writeElement(null, "href", XMLWriter.CLOSING);
+
+        String resourceName = path;
+        int lastSlash = path.lastIndexOf('/');
+        if (lastSlash != -1)
+            resourceName = resourceName.substring(lastSlash + 1);
+
+        switch (type) {
+
+        case FIND_ALL_PROP :
+
+            generatedXML.writeElement(null, "propstat", XMLWriter.OPENING);
+            generatedXML.writeElement(null, "prop", XMLWriter.OPENING);
+
+            generatedXML.writeProperty
+                (null, "creationdate",
+                 getISOCreationDate(cacheEntry.lastModified()));
+            generatedXML.writeElement(null, "displayname", XMLWriter.OPENING);
+            generatedXML.writeData(resourceName);
+            generatedXML.writeElement(null, "displayname", XMLWriter.CLOSING);
+            if (cacheEntry.isDirectory()) {
+                generatedXML.writeProperty
+                    (null, "getlastmodified", FastHttpDateFormat.formatDate
+                           (cacheEntry.lastModified(), null));
+                generatedXML.writeProperty
+                    (null, "getcontentlength",
+                     String.valueOf(cacheEntry.length()));
+                String contentType = 
+                    getServletContext().getMimeType(cacheEntry.getName());
+                if (contentType != null) {
+                    generatedXML.writeProperty(null, "getcontenttype",
+                                               contentType);
+                }
+                generatedXML.writeProperty(null, "getetag",
+                                           getETag(cacheEntry));
+                generatedXML.writeElement(null, "resourcetype",
+                                          XMLWriter.NO_CONTENT);
+            } else {
+                generatedXML.writeElement(null, "resourcetype",
+                                          XMLWriter.OPENING);
+                generatedXML.writeElement(null, "collection",
+                                          XMLWriter.NO_CONTENT);
+                generatedXML.writeElement(null, "resourcetype",
+                                          XMLWriter.CLOSING);
+            }
+
+            generatedXML.writeProperty(null, "source", "");
+
+            String supportedLocks = "<lockentry>"
+                + "<lockscope><exclusive/></lockscope>"
+                + "<locktype><write/></locktype>"
+                + "</lockentry>" + "<lockentry>"
+                + "<lockscope><shared/></lockscope>"
+                + "<locktype><write/></locktype>"
+                + "</lockentry>";
+            generatedXML.writeElement(null, "supportedlock",
+                                      XMLWriter.OPENING);
+            generatedXML.writeText(supportedLocks);
+            generatedXML.writeElement(null, "supportedlock",
+                                      XMLWriter.CLOSING);
+
+            generateLockDiscovery(path, generatedXML);
+
+            generatedXML.writeElement(null, "prop", XMLWriter.CLOSING);
+            generatedXML.writeElement(null, "status", XMLWriter.OPENING);
+            generatedXML.writeText(status);
+            generatedXML.writeElement(null, "status", XMLWriter.CLOSING);
+            generatedXML.writeElement(null, "propstat", XMLWriter.CLOSING);
+
+            break;
+
+        case FIND_PROPERTY_NAMES :
+
+            generatedXML.writeElement(null, "propstat", XMLWriter.OPENING);
+            generatedXML.writeElement(null, "prop", XMLWriter.OPENING);
+
+            generatedXML.writeElement(null, "creationdate",
+                                      XMLWriter.NO_CONTENT);
+            generatedXML.writeElement(null, "displayname",
+                                      XMLWriter.NO_CONTENT);
+            if (cacheEntry.isDirectory()) {
+                generatedXML.writeElement(null, "getcontentlanguage",
+                                          XMLWriter.NO_CONTENT);
+                generatedXML.writeElement(null, "getcontentlength",
+                                          XMLWriter.NO_CONTENT);
+                generatedXML.writeElement(null, "getcontenttype",
+                                          XMLWriter.NO_CONTENT);
+                generatedXML.writeElement(null, "getetag",
+                                          XMLWriter.NO_CONTENT);
+                generatedXML.writeElement(null, "getlastmodified",
+                                          XMLWriter.NO_CONTENT);
+            }
+            generatedXML.writeElement(null, "resourcetype",
+                                      XMLWriter.NO_CONTENT);
+            generatedXML.writeElement(null, "source", XMLWriter.NO_CONTENT);
+            generatedXML.writeElement(null, "lockdiscovery",
+                                      XMLWriter.NO_CONTENT);
+
+            generatedXML.writeElement(null, "prop", XMLWriter.CLOSING);
+            generatedXML.writeElement(null, "status", XMLWriter.OPENING);
+            generatedXML.writeText(status);
+            generatedXML.writeElement(null, "status", XMLWriter.CLOSING);
+            generatedXML.writeElement(null, "propstat", XMLWriter.CLOSING);
+
+            break;
+
+        case FIND_BY_PROPERTY :
+
+            Vector propertiesNotFound = new Vector();
+
+            // Parse the list of properties
+
+            generatedXML.writeElement(null, "propstat", XMLWriter.OPENING);
+            generatedXML.writeElement(null, "prop", XMLWriter.OPENING);
+
+            Enumeration properties = propertiesVector.elements();
+
+            while (properties.hasMoreElements()) {
+
+                String property = (String) properties.nextElement();
+
+                if (property.equals("creationdate")) {
+                    generatedXML.writeProperty
+                        (null, "creationdate",
+                         getISOCreationDate(cacheEntry.lastModified()));
+                } else if (property.equals("displayname")) {
+                    generatedXML.writeElement
+                        (null, "displayname", XMLWriter.OPENING);
+                    generatedXML.writeData(resourceName);
+                    generatedXML.writeElement
+                        (null, "displayname", XMLWriter.CLOSING);
+                } else if (property.equals("getcontentlanguage")) {
+                    if (cacheEntry.isDirectory()) {
+                        propertiesNotFound.addElement(property);
+                    } else {
+                        generatedXML.writeElement(null, "getcontentlanguage",
+                                                  XMLWriter.NO_CONTENT);
+                    }
+                } else if (property.equals("getcontentlength")) {
+                    if (cacheEntry.isDirectory()) {
+                        propertiesNotFound.addElement(property);
+                    } else {
+                        generatedXML.writeProperty
+                            (null, "getcontentlength",
+                             (String.valueOf(cacheEntry.length())));
+                    }
+                } else if (property.equals("getcontenttype")) {
+                    if (cacheEntry.isDirectory()) {
+                        propertiesNotFound.addElement(property);
+                    } else {
+                        generatedXML.writeProperty
+                            (null, "getcontenttype",
+                             getServletContext().getMimeType
+                             (cacheEntry.getName()));
+                    }
+                } else if (property.equals("getetag")) {
+                    if (cacheEntry.isDirectory()) {
+                        propertiesNotFound.addElement(property);
+                    } else {
+                        generatedXML.writeProperty
+                            (null, "getetag", getETag(cacheEntry));
+                    }
+                } else if (property.equals("getlastmodified")) {
+                    if (cacheEntry.isDirectory()) {
+                        propertiesNotFound.addElement(property);
+                    } else {
+                        generatedXML.writeProperty
+                            (null, "getlastmodified", FastHttpDateFormat.formatDate
+                                    (cacheEntry.lastModified(), null));
+                    }
+                } else if (property.equals("resourcetype")) {
+                    if (cacheEntry.isDirectory()) {
+                        generatedXML.writeElement(null, "resourcetype",
+                                                  XMLWriter.OPENING);
+                        generatedXML.writeElement(null, "collection",
+                                                  XMLWriter.NO_CONTENT);
+                        generatedXML.writeElement(null, "resourcetype",
+                                                  XMLWriter.CLOSING);
+                    } else {
+                        generatedXML.writeElement(null, "resourcetype",
+                                                  XMLWriter.NO_CONTENT);
+                    }
+                } else if (property.equals("source")) {
+                    generatedXML.writeProperty(null, "source", "");
+                } else if (property.equals("supportedlock")) {
+                    supportedLocks = "<lockentry>"
+                        + "<lockscope><exclusive/></lockscope>"
+                        + "<locktype><write/></locktype>"
+                        + "</lockentry>" + "<lockentry>"
+                        + "<lockscope><shared/></lockscope>"
+                        + "<locktype><write/></locktype>"
+                        + "</lockentry>";
+                    generatedXML.writeElement(null, "supportedlock",
+                                              XMLWriter.OPENING);
+                    generatedXML.writeText(supportedLocks);
+                    generatedXML.writeElement(null, "supportedlock",
+                                              XMLWriter.CLOSING);
+                    propertiesNotFound.addElement(property);
+                } else if (property.equals("lockdiscovery")) {
+                    if (!generateLockDiscovery(path, generatedXML))
+                        propertiesNotFound.addElement(property);
+                    propertiesNotFound.addElement(property);
+                } else {
+                    propertiesNotFound.addElement(property);
+                }
+
+            }
+
+            generatedXML.writeElement(null, "prop", XMLWriter.CLOSING);
+            generatedXML.writeElement(null, "status", XMLWriter.OPENING);
+            generatedXML.writeText(status);
+            generatedXML.writeElement(null, "status", XMLWriter.CLOSING);
+            generatedXML.writeElement(null, "propstat", XMLWriter.CLOSING);
+
+            Enumeration propertiesNotFoundList = propertiesNotFound.elements();
+
+            if (propertiesNotFoundList.hasMoreElements()) {
+
+                status = new String("HTTP/1.1 " + WebdavStatus.SC_NOT_FOUND
+                                    + " " + WebdavStatus.getStatusText
+                                    (WebdavStatus.SC_NOT_FOUND));
+
+                generatedXML.writeElement(null, "propstat", XMLWriter.OPENING);
+                generatedXML.writeElement(null, "prop", XMLWriter.OPENING);
+
+                while (propertiesNotFoundList.hasMoreElements()) {
+                    generatedXML.writeElement
+                        (null, (String) propertiesNotFoundList.nextElement(),
+                         XMLWriter.NO_CONTENT);
+                }
+
+                generatedXML.writeElement(null, "prop", XMLWriter.CLOSING);
+                generatedXML.writeElement(null, "status", XMLWriter.OPENING);
+                generatedXML.writeText(status);
+                generatedXML.writeElement(null, "status", XMLWriter.CLOSING);
+                generatedXML.writeElement(null, "propstat", XMLWriter.CLOSING);
+
+            }
+
+            break;
+
+        }
+
+        generatedXML.writeElement(null, "response", XMLWriter.CLOSING);
+
+    }
+
+
+    /**
+     * Propfind helper method. Dispays the properties of a lock-null resource.
+     *
+     * @param resources Resources object associated with this context
+     * @param generatedXML XML response to the Propfind request
+     * @param path Path of the current resource
+     * @param type Propfind type
+     * @param propertiesVector If the propfind type is find properties by
+     * name, then this Vector contains those properties
+     */
+    private void parseLockNullProperties(HttpServletRequest req,
+                                         XMLWriter generatedXML,
+                                         String path, int type,
+                                         Vector propertiesVector) {
+
+        // Exclude any resource in the /WEB-INF and /META-INF subdirectories
+        // (the "toUpperCase()" avoids problems on Windows systems)
+        if (path.toUpperCase().startsWith("/WEB-INF") ||
+            path.toUpperCase().startsWith("/META-INF"))
+            return;
+
+        // Retrieving the lock associated with the lock-null resource
+        LockInfo lock = (LockInfo) resourceLocks.get(path);
+
+        if (lock == null)
+            return;
+
+        generatedXML.writeElement(null, "response", XMLWriter.OPENING);
+        String status = new String("HTTP/1.1 " + WebdavStatus.SC_OK + " "
+                                   + WebdavStatus.getStatusText
+                                   (WebdavStatus.SC_OK));
+
+        // Generating href element
+        generatedXML.writeElement(null, "href", XMLWriter.OPENING);
+
+        String absoluteUri = req.getRequestURI();
+        String relativePath = getRelativePath(req);
+        String toAppend = path.substring(relativePath.length());
+        if (!toAppend.startsWith("/"))
+            toAppend = "/" + toAppend;
+
+        generatedXML.writeText(rewriteUrl(UrlUtils.normalize(absoluteUri + toAppend)));
+
+        generatedXML.writeElement(null, "href", XMLWriter.CLOSING);
+
+        String resourceName = path;
+        int lastSlash = path.lastIndexOf('/');
+        if (lastSlash != -1)
+            resourceName = resourceName.substring(lastSlash + 1);
+
+        switch (type) {
+
+        case FIND_ALL_PROP :
+
+            generatedXML.writeElement(null, "propstat", XMLWriter.OPENING);
+            generatedXML.writeElement(null, "prop", XMLWriter.OPENING);
+
+            generatedXML.writeProperty
+                (null, "creationdate",
+                 getISOCreationDate(lock.creationDate.getTime()));
+            generatedXML.writeElement
+                (null, "displayname", XMLWriter.OPENING);
+            generatedXML.writeData(resourceName);
+            generatedXML.writeElement
+                (null, "displayname", XMLWriter.CLOSING);
+            generatedXML.writeProperty(null, "getlastmodified",
+                                       FastHttpDateFormat.formatDate
+                                       (lock.creationDate.getTime(), null));
+            generatedXML.writeProperty
+                (null, "getcontentlength", String.valueOf(0));
+            generatedXML.writeProperty(null, "getcontenttype", "");
+            generatedXML.writeProperty(null, "getetag", "");
+            generatedXML.writeElement(null, "resourcetype",
+                                      XMLWriter.OPENING);
+            generatedXML.writeElement(null, "lock-null", XMLWriter.NO_CONTENT);
+            generatedXML.writeElement(null, "resourcetype",
+                                      XMLWriter.CLOSING);
+
+            generatedXML.writeProperty(null, "source", "");
+
+            String supportedLocks = "<lockentry>"
+                + "<lockscope><exclusive/></lockscope>"
+                + "<locktype><write/></locktype>"
+                + "</lockentry>" + "<lockentry>"
+                + "<lockscope><shared/></lockscope>"
+                + "<locktype><write/></locktype>"
+                + "</lockentry>";
+            generatedXML.writeElement(null, "supportedlock",
+                                      XMLWriter.OPENING);
+            generatedXML.writeText(supportedLocks);
+            generatedXML.writeElement(null, "supportedlock",
+                                      XMLWriter.CLOSING);
+
+           generateLockDiscovery(path, generatedXML);
+
+            generatedXML.writeElement(null, "prop", XMLWriter.CLOSING);
+            generatedXML.writeElement(null, "status", XMLWriter.OPENING);
+            generatedXML.writeText(status);
+            generatedXML.writeElement(null, "status", XMLWriter.CLOSING);
+            generatedXML.writeElement(null, "propstat", XMLWriter.CLOSING);
+
+            break;
+
+        case FIND_PROPERTY_NAMES :
+
+            generatedXML.writeElement(null, "propstat", XMLWriter.OPENING);
+            generatedXML.writeElement(null, "prop", XMLWriter.OPENING);
+
+            generatedXML.writeElement(null, "creationdate",
+                                      XMLWriter.NO_CONTENT);
+            generatedXML.writeElement(null, "displayname",
+                                      XMLWriter.NO_CONTENT);
+            generatedXML.writeElement(null, "getcontentlanguage",
+                                      XMLWriter.NO_CONTENT);
+            generatedXML.writeElement(null, "getcontentlength",
+                                      XMLWriter.NO_CONTENT);
+            generatedXML.writeElement(null, "getcontenttype",
+                                      XMLWriter.NO_CONTENT);
+            generatedXML.writeElement(null, "getetag",
+                                      XMLWriter.NO_CONTENT);
+            generatedXML.writeElement(null, "getlastmodified",
+                                      XMLWriter.NO_CONTENT);
+            generatedXML.writeElement(null, "resourcetype",
+                                      XMLWriter.NO_CONTENT);
+            generatedXML.writeElement(null, "source",
+                                      XMLWriter.NO_CONTENT);
+            generatedXML.writeElement(null, "lockdiscovery",
+                                      XMLWriter.NO_CONTENT);
+
+            generatedXML.writeElement(null, "prop", XMLWriter.CLOSING);
+            generatedXML.writeElement(null, "status", XMLWriter.OPENING);
+            generatedXML.writeText(status);
+            generatedXML.writeElement(null, "status", XMLWriter.CLOSING);
+            generatedXML.writeElement(null, "propstat", XMLWriter.CLOSING);
+
+            break;
+
+        case FIND_BY_PROPERTY :
+
+            Vector propertiesNotFound = new Vector();
+
+            // Parse the list of properties
+
+            generatedXML.writeElement(null, "propstat", XMLWriter.OPENING);
+            generatedXML.writeElement(null, "prop", XMLWriter.OPENING);
+
+            Enumeration properties = propertiesVector.elements();
+
+            while (properties.hasMoreElements()) {
+
+                String property = (String) properties.nextElement();
+
+                if (property.equals("creationdate")) {
+                    generatedXML.writeProperty
+                        (null, "creationdate",
+                         getISOCreationDate(lock.creationDate.getTime()));
+                } else if (property.equals("displayname")) {
+                    generatedXML.writeElement
+                        (null, "displayname", XMLWriter.OPENING);
+                    generatedXML.writeData(resourceName);
+                    generatedXML.writeElement
+                        (null, "displayname", XMLWriter.CLOSING);
+                } else if (property.equals("getcontentlanguage")) {
+                    generatedXML.writeElement(null, "getcontentlanguage",
+                                              XMLWriter.NO_CONTENT);
+                } else if (property.equals("getcontentlength")) {
+                    generatedXML.writeProperty
+                        (null, "getcontentlength", (String.valueOf(0)));
+                } else if (property.equals("getcontenttype")) {
+                    generatedXML.writeProperty
+                        (null, "getcontenttype", "");
+                } else if (property.equals("getetag")) {
+                    generatedXML.writeProperty(null, "getetag", "");
+                } else if (property.equals("getlastmodified")) {
+                    generatedXML.writeProperty
+                        (null, "getlastmodified",
+                          FastHttpDateFormat.formatDate
+                         (lock.creationDate.getTime(), null));
+                } else if (property.equals("resourcetype")) {
+                    generatedXML.writeElement(null, "resourcetype",
+                                              XMLWriter.OPENING);
+                    generatedXML.writeElement(null, "lock-null",
+                                              XMLWriter.NO_CONTENT);
+                    generatedXML.writeElement(null, "resourcetype",
+                                              XMLWriter.CLOSING);
+                } else if (property.equals("source")) {
+                    generatedXML.writeProperty(null, "source", "");
+                } else if (property.equals("supportedlock")) {
+                    supportedLocks = "<lockentry>"
+                        + "<lockscope><exclusive/></lockscope>"
+                        + "<locktype><write/></locktype>"
+                        + "</lockentry>" + "<lockentry>"
+                        + "<lockscope><shared/></lockscope>"
+                        + "<locktype><write/></locktype>"
+                        + "</lockentry>";
+                    generatedXML.writeElement(null, "supportedlock",
+                                              XMLWriter.OPENING);
+                    generatedXML.writeText(supportedLocks);
+                    generatedXML.writeElement(null, "supportedlock",
+                                              XMLWriter.CLOSING);
+                    propertiesNotFound.addElement(property);
+                } else if (property.equals("lockdiscovery")) {
+                    if (!generateLockDiscovery(path, generatedXML))
+                        propertiesNotFound.addElement(property);
+                    propertiesNotFound.addElement(property);
+                } else {
+                    propertiesNotFound.addElement(property);
+                }
+
+            }
+
+            generatedXML.writeElement(null, "prop", XMLWriter.CLOSING);
+            generatedXML.writeElement(null, "status", XMLWriter.OPENING);
+            generatedXML.writeText(status);
+            generatedXML.writeElement(null, "status", XMLWriter.CLOSING);
+            generatedXML.writeElement(null, "propstat", XMLWriter.CLOSING);
+
+            Enumeration propertiesNotFoundList = propertiesNotFound.elements();
+
+            if (propertiesNotFoundList.hasMoreElements()) {
+
+                status = new String("HTTP/1.1 " + WebdavStatus.SC_NOT_FOUND
+                                    + " " + WebdavStatus.getStatusText
+                                    (WebdavStatus.SC_NOT_FOUND));
+
+                generatedXML.writeElement(null, "propstat", XMLWriter.OPENING);
+                generatedXML.writeElement(null, "prop", XMLWriter.OPENING);
+
+                while (propertiesNotFoundList.hasMoreElements()) {
+                    generatedXML.writeElement
+                        (null, (String) propertiesNotFoundList.nextElement(),
+                         XMLWriter.NO_CONTENT);
+                }
+
+                generatedXML.writeElement(null, "prop", XMLWriter.CLOSING);
+                generatedXML.writeElement(null, "status", XMLWriter.OPENING);
+                generatedXML.writeText(status);
+                generatedXML.writeElement(null, "status", XMLWriter.CLOSING);
+                generatedXML.writeElement(null, "propstat", XMLWriter.CLOSING);
+
+            }
+
+            break;
+
+        }
+
+        generatedXML.writeElement(null, "response", XMLWriter.CLOSING);
+
+    }
+
+
+    /**
+     * Print the lock discovery information associated with a path.
+     *
+     * @param path Path
+     * @param generatedXML XML data to which the locks info will be appended
+     * @return true if at least one lock was displayed
+     */
+    private boolean generateLockDiscovery
+        (String path, XMLWriter generatedXML) {
+
+        LockInfo resourceLock = (LockInfo) resourceLocks.get(path);
+        Enumeration collectionLocksList = collectionLocks.elements();
+
+        boolean wroteStart = false;
+
+        if (resourceLock != null) {
+            wroteStart = true;
+            generatedXML.writeElement(null, "lockdiscovery",
+                                      XMLWriter.OPENING);
+            resourceLock.toXML(generatedXML);
+        }
+
+        while (collectionLocksList.hasMoreElements()) {
+            LockInfo currentLock =
+                (LockInfo) collectionLocksList.nextElement();
+            if (path.startsWith(currentLock.path)) {
+                if (!wroteStart) {
+                    wroteStart = true;
+                    generatedXML.writeElement(null, "lockdiscovery",
+                                              XMLWriter.OPENING);
+                }
+                currentLock.toXML(generatedXML);
+            }
+        }
+
+        if (wroteStart) {
+            generatedXML.writeElement(null, "lockdiscovery",
+                                      XMLWriter.CLOSING);
+        } else {
+            return false;
+        }
+
+        return true;
+
+    }
+
+
+    // --------------------------------------------------  LockInfo Inner Class
+
+
+    /**
+     * Holds a lock information.
+     */
+    private class LockInfo {
+
+
+        // -------------------------------------------------------- Constructor
+
+
+        /**
+         * Constructor.
+         */
+        public LockInfo() {
+
+        }
+
+
+        // ------------------------------------------------- Instance Variables
+
+
+        String path = "/";
+        String type = "write";
+        String scope = "exclusive";
+        int depth = 0;
+        String owner = "";
+        Vector tokens = new Vector();
+        long expiresAt = 0;
+        Date creationDate = new Date();
+
+
+        // ----------------------------------------------------- Public Methods
+
+
+        /**
+         * Get a String representation of this lock token.
+         */
+        public String toString() {
+
+            String result =  "Type:" + type + "\n";
+            result += "Scope:" + scope + "\n";
+            result += "Depth:" + depth + "\n";
+            result += "Owner:" + owner + "\n";
+            result += "Expiration:"
+                + FastHttpDateFormat.formatDate(expiresAt, null) + "\n";
+            Enumeration tokensList = tokens.elements();
+            while (tokensList.hasMoreElements()) {
+                result += "Token:" + tokensList.nextElement() + "\n";
+            }
+            return result;
+
+        }
+
+
+        /**
+         * Return true if the lock has expired.
+         */
+        public boolean hasExpired() {
+            return (System.currentTimeMillis() > expiresAt);
+        }
+
+
+        /**
+         * Return true if the lock is exclusive.
+         */
+        public boolean isExclusive() {
+
+            return (scope.equals("exclusive"));
+
+        }
+
+
+        /**
+         * Get an XML representation of this lock token. This method will
+         * append an XML fragment to the given XML writer.
+         */
+        public void toXML(XMLWriter generatedXML) {
+
+            generatedXML.writeElement(null, "activelock", XMLWriter.OPENING);
+
+            generatedXML.writeElement(null, "locktype", XMLWriter.OPENING);
+            generatedXML.writeElement(null, type, XMLWriter.NO_CONTENT);
+            generatedXML.writeElement(null, "locktype", XMLWriter.CLOSING);
+
+            generatedXML.writeElement(null, "lockscope", XMLWriter.OPENING);
+            generatedXML.writeElement(null, scope, XMLWriter.NO_CONTENT);
+            generatedXML.writeElement(null, "lockscope", XMLWriter.CLOSING);
+
+            generatedXML.writeElement(null, "depth", XMLWriter.OPENING);
+            if (depth == INFINITY) {
+                generatedXML.writeText("Infinity");
+            } else {
+                generatedXML.writeText("0");
+            }
+            generatedXML.writeElement(null, "depth", XMLWriter.CLOSING);
+
+            generatedXML.writeElement(null, "owner", XMLWriter.OPENING);
+            generatedXML.writeText(owner);
+            generatedXML.writeElement(null, "owner", XMLWriter.CLOSING);
+
+            generatedXML.writeElement(null, "timeout", XMLWriter.OPENING);
+            long timeout = (expiresAt - System.currentTimeMillis()) / 1000;
+            generatedXML.writeText("Second-" + timeout);
+            generatedXML.writeElement(null, "timeout", XMLWriter.CLOSING);
+
+            generatedXML.writeElement(null, "locktoken", XMLWriter.OPENING);
+            Enumeration tokensList = tokens.elements();
+            while (tokensList.hasMoreElements()) {
+                generatedXML.writeElement(null, "href", XMLWriter.OPENING);
+                generatedXML.writeText("opaquelocktoken:"
+                                       + tokensList.nextElement());
+                generatedXML.writeElement(null, "href", XMLWriter.CLOSING);
+            }
+            generatedXML.writeElement(null, "locktoken", XMLWriter.CLOSING);
+
+            generatedXML.writeElement(null, "activelock", XMLWriter.CLOSING);
+
+        }
+
+
+    }
+
+
+    private class Property {
+
+        public String name;
+        public String value;
+        public String namespace;
+        public String namespaceAbbrev;
+        public int status = WebdavStatus.SC_OK;
+
+    }
+
+    /**
+     * A sample DOM writer. This sample program illustrates how to
+     * traverse a DOM tree in order to print a document that is parsed.
+     */
+    public static class DOMWriter {
+
+       /** Output qualified names */
+       private boolean qualifiedNames = true;
+
+       /** Print writer. */
+       protected PrintWriter out;
+
+       /** Canonical output. */
+       protected boolean canonical;
+
+       public DOMWriter(Writer writer, boolean canonical) {
+            out = new PrintWriter(writer);
+            this.canonical = canonical;
+        }
+
+       public void setQualifiedNames(boolean qualifiedNames) {
+          this.qualifiedNames = qualifiedNames;
+       }
+
+       /** Prints the specified node, recursively. */
+       public void print(Node node) {
+
+          // is there anything to do?
+          if ( node == null ) {
+             return;
+          }
+
+          int type = node.getNodeType();
+          switch ( type ) {
+             // print document
+             case Node.DOCUMENT_NODE: {
+                   if ( !canonical ) {
+                      String Encoding = "UTF-8";
+
+                      out.println("<?xml version=\"1.0\" encoding=\""+
+                               Encoding + "\"?>");
+                   }
+                   print(((Document)node).getDocumentElement());
+                   out.flush();
+                   break;
+                }
+
+                // print element with attributes
+             case Node.ELEMENT_NODE: {
+                   out.print('<');
+                   if (this.qualifiedNames) { 
+                      out.print(node.getNodeName());
+                   } else {
+                      out.print(node.getLocalName());
+                   }
+                   Attr attrs[] = sortAttributes(node.getAttributes());
+                   for ( int i = 0; i < attrs.length; i++ ) {
+                      Attr attr = attrs[i];
+                      out.print(' ');
+                      if (this.qualifiedNames) {
+                         out.print(attr.getNodeName());
+                      } else {
+                         out.print(attr.getLocalName());
+                      }
+                      
+                      out.print("=\"");
+                      out.print(normalize(attr.getNodeValue()));
+                      out.print('"');
+                   }
+                   out.print('>');
+                   NodeList children = node.getChildNodes();
+                   if ( children != null ) {
+                      int len = children.getLength();
+                      for ( int i = 0; i < len; i++ ) {
+                         print(children.item(i));
+                      }
+                   }
+                   break;
+                }
+
+                // handle entity reference nodes
+             case Node.ENTITY_REFERENCE_NODE: {
+                   if ( canonical ) {
+                      NodeList children = node.getChildNodes();
+                      if ( children != null ) {
+                         int len = children.getLength();
+                         for ( int i = 0; i < len; i++ ) {
+                            print(children.item(i));
+                         }
+                      }
+                   } else {
+                      out.print('&');
+                      if (this.qualifiedNames) {
+                         out.print(node.getNodeName());
+                      } else {
+                         out.print(node.getLocalName());
+                      }
+                      out.print(';');
+                   }
+                   break;
+                }
+
+                // print cdata sections
+             case Node.CDATA_SECTION_NODE: {
+                   if ( canonical ) {
+                      out.print(normalize(node.getNodeValue()));
+                   } else {
+                      out.print("<![CDATA[");
+                      out.print(node.getNodeValue());
+                      out.print("]]>");
+                   }
+                   break;
+                }
+
+                // print text
+             case Node.TEXT_NODE: {
+                   out.print(normalize(node.getNodeValue()));
+                   break;
+                }
+
+                // print processing instruction
+             case Node.PROCESSING_INSTRUCTION_NODE: {
+                   out.print("<?");
+                   if (this.qualifiedNames) {
+                      out.print(node.getNodeName());
+                   } else {
+                      out.print(node.getLocalName());
+                   }
+                   
+                   String data = node.getNodeValue();
+                   if ( data != null && data.length() > 0 ) {
+                      out.print(' ');
+                      out.print(data);
+                   }
+                   out.print("?>");
+                   break;
+                }
+          }
+
+          if ( type == Node.ELEMENT_NODE ) {
+             out.print("</");
+             if (this.qualifiedNames) {
+                out.print(node.getNodeName());
+             } else {
+                out.print(node.getLocalName());
+             }
+             out.print('>');
+          }
+
+          out.flush();
+
+       } // print(Node)
+
+       /** Returns a sorted list of attributes. */
+       private Attr[] sortAttributes(NamedNodeMap attrs) {
+
+          int len = (attrs != null) ? attrs.getLength() : 0;
+          Attr array[] = new Attr[len];
+          for ( int i = 0; i < len; i++ ) {
+             array[i] = (Attr)attrs.item(i);
+          }
+          for ( int i = 0; i < len - 1; i++ ) {
+             String name = null;
+             if (this.qualifiedNames) {
+                name  = array[i].getNodeName();
+             } else {
+                name  = array[i].getLocalName();
+             }
+             int    index = i;
+             for ( int j = i + 1; j < len; j++ ) {
+                String curName = null;
+                if (this.qualifiedNames) {
+                   curName = array[j].getNodeName();
+                } else {
+                   curName = array[j].getLocalName();
+                }
+                if ( curName.compareTo(name) < 0 ) {
+                   name  = curName;
+                   index = j;
+                }
+             }
+             if ( index != i ) {
+                Attr temp    = array[i];
+                array[i]     = array[index];
+                array[index] = temp;
+             }
+          }
+
+          return (array);
+
+       } // sortAttributes(NamedNodeMap):Attr[]
+
+
+       /** Normalizes the given string. */
+       private String normalize(String s) {
+          StringBuffer str = new StringBuffer();
+
+          int len = (s != null) ? s.length() : 0;
+          for ( int i = 0; i < len; i++ ) {
+             char ch = s.charAt(i);
+             switch ( ch ) {
+                case '<': {
+                      str.append("&lt;");
+                      break;
+                   }
+                case '>': {
+                      str.append("&gt;");
+                      break;
+                   }
+                case '&': {
+                      str.append("&amp;");
+                      break;
+                   }
+                case '"': {
+                      str.append("&quot;");
+                      break;
+                   }
+                case '\r':
+                case '\n': {
+                      if ( canonical ) {
+                         str.append("&#");
+                         str.append(Integer.toString(ch));
+                         str.append(';');
+                         break;
+                      }
+                      // else, default append char
+                   }
+                default: {
+                      str.append(ch);
+                   }
+             }
+          }
+
+          return (str.toString());
+
+       } // normalize(String):String
+
+    }
+
+
+};

Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/WebdavServlet.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/WebdavServlet.java?view=diff&rev=534293&r1=534292&r2=534293
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/WebdavServlet.java (original)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/WebdavServlet.java Tue May  1 19:22:45 2007
@@ -35,16 +35,16 @@
 import javax.servlet.ServletException;
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
+
 import javax.xml.parsers.DocumentBuilder;
 import javax.xml.parsers.DocumentBuilderFactory;
 import javax.xml.parsers.ParserConfigurationException;
 
-import org.apache.tomcat.servlets.util.CopyUtils;
-import org.apache.tomcat.servlets.util.Range;
-import org.apache.tomcat.servlets.util.RequestUtil;
 import org.apache.tomcat.servlets.util.UrlUtils;
-import org.apache.tomcat.servlets.util.XMLWriter;
 import org.apache.tomcat.util.http.FastHttpDateFormat;
+import org.apache.tomcat.util.http.Range;
+import org.apache.tomcat.util.http.RequestUtil;
+
 import org.w3c.dom.Document;
 import org.w3c.dom.Element;
 import org.w3c.dom.Node;

Added: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/XMLWriter.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/XMLWriter.java?view=auto&rev=534293
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/XMLWriter.java (added)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/file/XMLWriter.java Tue May  1 19:22:45 2007
@@ -0,0 +1,243 @@
+/*
+ * Copyright 1999,2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.apache.tomcat.servlets.file;
+
+import java.io.IOException;
+import java.io.Writer;
+
+/**
+ * XMLWriter helper class.
+ *
+ * @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
+ */
+public class XMLWriter {
+
+
+    // -------------------------------------------------------------- Constants
+
+
+    /**
+     * Opening tag.
+     */
+    public static final int OPENING = 0;
+
+
+    /**
+     * Closing tag.
+     */
+    public static final int CLOSING = 1;
+
+
+    /**
+     * Element with no content.
+     */
+    public static final int NO_CONTENT = 2;
+
+
+    // ----------------------------------------------------- Instance Variables
+
+
+    /**
+     * Buffer.
+     */
+    protected StringBuffer buffer = new StringBuffer();
+
+
+    /**
+     * Writer.
+     */
+    protected Writer writer = null;
+
+
+    // ----------------------------------------------------------- Constructors
+
+
+    /**
+     * Constructor.
+     */
+    public XMLWriter() {
+    }
+
+
+    /**
+     * Constructor.
+     */
+    public XMLWriter(Writer writer) {
+        this.writer = writer;
+    }
+
+
+    // --------------------------------------------------------- Public Methods
+
+
+    /**
+     * Retrieve generated XML.
+     *
+     * @return String containing the generated XML
+     */
+    public String toString() {
+        return buffer.toString();
+    }
+
+
+    /**
+     * Write property to the XML.
+     *
+     * @param namespace Namespace
+     * @param namespaceInfo Namespace info
+     * @param name Property name
+     * @param value Property value
+     */
+    public void writeProperty(String namespace, String namespaceInfo,
+                              String name, String value) {
+        writeElement(namespace, namespaceInfo, name, OPENING);
+        buffer.append(value);
+        writeElement(namespace, namespaceInfo, name, CLOSING);
+
+    }
+
+
+    /**
+     * Write property to the XML.
+     *
+     * @param namespace Namespace
+     * @param name Property name
+     * @param value Property value
+     */
+    public void writeProperty(String namespace, String name, String value) {
+        writeElement(namespace, name, OPENING);
+        buffer.append(value);
+        writeElement(namespace, name, CLOSING);
+    }
+
+
+    /**
+     * Write property to the XML.
+     *
+     * @param namespace Namespace
+     * @param name Property name
+     */
+    public void writeProperty(String namespace, String name) {
+        writeElement(namespace, name, NO_CONTENT);
+    }
+
+
+    /**
+     * Write an element.
+     *
+     * @param name Element name
+     * @param namespace Namespace abbreviation
+     * @param type Element type
+     */
+    public void writeElement(String namespace, String name, int type) {
+        writeElement(namespace, null, name, type);
+    }
+
+
+    /**
+     * Write an element.
+     *
+     * @param namespace Namespace abbreviation
+     * @param namespaceInfo Namespace info
+     * @param name Element name
+     * @param type Element type
+     */
+    public void writeElement(String namespace, String namespaceInfo,
+                             String name, int type) {
+        if ((namespace != null) && (namespace.length() > 0)) {
+            switch (type) {
+            case OPENING:
+                if (namespaceInfo != null) {
+                    buffer.append("<" + namespace + ":" + name + " xmlns:"
+                                  + namespace + "=\""
+                                  + namespaceInfo + "\">");
+                } else {
+                    buffer.append("<" + namespace + ":" + name + ">");
+                }
+                break;
+            case CLOSING:
+                buffer.append("</" + namespace + ":" + name + ">\n");
+                break;
+            case NO_CONTENT:
+            default:
+                if (namespaceInfo != null) {
+                    buffer.append("<" + namespace + ":" + name + " xmlns:"
+                                  + namespace + "=\""
+                                  + namespaceInfo + "\"/>");
+                } else {
+                    buffer.append("<" + namespace + ":" + name + "/>");
+                }
+                break;
+            }
+        } else {
+            switch (type) {
+            case OPENING:
+                buffer.append("<" + name + ">");
+                break;
+            case CLOSING:
+                buffer.append("</" + name + ">\n");
+                break;
+            case NO_CONTENT:
+            default:
+                buffer.append("<" + name + "/>");
+                break;
+            }
+        }
+    }
+
+
+    /**
+     * Write text.
+     *
+     * @param text Text to append
+     */
+    public void writeText(String text) {
+        buffer.append(text);
+    }
+
+
+    /**
+     * Write data.
+     *
+     * @param data Data to append
+     */
+    public void writeData(String data) {
+        buffer.append("<![CDATA[" + data + "]]>");
+    }
+
+
+    /**
+     * Write XML Header.
+     */
+    public void writeXMLHeader() {
+        buffer.append("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n");
+    }
+
+
+    /**
+     * Send data and reinitializes buffer.
+     */
+    public void sendData()
+        throws IOException {
+        if (writer != null) {
+            writer.write(buffer.toString());
+            buffer = new StringBuffer();
+        }
+    }
+
+
+}

Modified: tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/JspProxyServlet.java
URL: http://svn.apache.org/viewvc/tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/JspProxyServlet.java?view=diff&rev=534293&r1=534292&r2=534293
==============================================================================
--- tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/JspProxyServlet.java (original)
+++ tomcat/sandbox/tomcat-lite/java/org/apache/tomcat/servlets/jsp/JspProxyServlet.java Tue May  1 19:22:45 2007
@@ -12,15 +12,17 @@
 import javax.servlet.http.HttpServletRequest;
 import javax.servlet.http.HttpServletResponse;
 
-import org.apache.coyote.Request;
-import org.apache.coyote.Response;
 import org.apache.jasper.Constants;
 import org.apache.jasper.JasperException;
 import org.apache.jasper.JspC;
-import org.apache.tomcat.lite.ServletConfigImpl;
 import org.apache.tomcat.lite.ServletContextImpl;
-import org.apache.tomcat.lite.ServletRequestImpl;
-import org.apache.tomcat.lite.ServletResponseImpl;
+
+/*
+ 
+   <servlet><servlet-name>_jsp</servlet-name><servlet-class>org.apache.tomcat.servlets.jsp.JspProxyServlet</servlet-class></servlet>
+   <servlet-mapping><servlet-name>_jsp</servlet-name><url-pattern>*.jsp</url-pattern></servlet-mapping>
+ 
+ */
 
 /** 
  * If jasper is found, it'll just forward the calls to jasper jsp servlet.



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


Mime
View raw message