Source Code Cross Referenced for WebdavServlet.java in  » Web-Server » Rimfaxe-Web-Server » org » apache » catalina » servlets » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Web Server » Rimfaxe Web Server » org.apache.catalina.servlets 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * $Header: /home/cvs/jakarta-tomcat-4.0/catalina/src/share/org/apache/catalina/servlets/WebdavServlet.java,v 1.28 2002/04/01 18:12:38 remm Exp $
0003:         * $Revision: 1.28 $
0004:         * $Date: 2002/04/01 18:12:38 $
0005:         *
0006:         * ====================================================================
0007:         *
0008:         * The Apache Software License, Version 1.1
0009:         *
0010:         * Copyright (c) 1999 The Apache Software Foundation.  All rights
0011:         * reserved.
0012:         *
0013:         * Redistribution and use in source and binary forms, with or without
0014:         * modification, are permitted provided that the following conditions
0015:         * are met:
0016:         *
0017:         * 1. Redistributions of source code must retain the above copyright
0018:         *    notice, this list of conditions and the following disclaimer.
0019:         *
0020:         * 2. Redistributions in binary form must reproduce the above copyright
0021:         *    notice, this list of conditions and the following disclaimer in
0022:         *    the documentation and/or other materials provided with the
0023:         *    distribution.
0024:         *
0025:         * 3. The end-user documentation included with the redistribution, if
0026:         *    any, must include the following acknowlegement:
0027:         *       "This product includes software developed by the
0028:         *        Apache Software Foundation (http://www.apache.org/)."
0029:         *    Alternately, this acknowlegement may appear in the software itself,
0030:         *    if and wherever such third-party acknowlegements normally appear.
0031:         *
0032:         * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
0033:         *    Foundation" must not be used to endorse or promote products derived
0034:         *    from this software without prior written permission. For written
0035:         *    permission, please contact apache@apache.org.
0036:         *
0037:         * 5. Products derived from this software may not be called "Apache"
0038:         *    nor may "Apache" appear in their names without prior written
0039:         *    permission of the Apache Group.
0040:         *
0041:         * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
0042:         * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
0043:         * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
0044:         * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
0045:         * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0046:         * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0047:         * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
0048:         * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
0049:         * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
0050:         * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
0051:         * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
0052:         * SUCH DAMAGE.
0053:         * ====================================================================
0054:         *
0055:         * This software consists of voluntary contributions made by many
0056:         * individuals on behalf of the Apache Software Foundation.  For more
0057:         * information on the Apache Software Foundation, please see
0058:         * <http://www.apache.org/>.
0059:         *
0060:         * [Additional notices, if required by prior licensing conditions]
0061:         *
0062:         */
0063:
0064:        package org.apache.catalina.servlets;
0065:
0066:        import java.io.BufferedInputStream;
0067:        import java.io.File;
0068:        import java.io.FileInputStream;
0069:        import java.io.InputStream;
0070:        import java.io.IOException;
0071:        import java.io.PrintWriter;
0072:        import java.io.StringWriter;
0073:        import java.io.Writer;
0074:        import java.net.MalformedURLException;
0075:        import java.net.URL;
0076:        import java.sql.Timestamp;
0077:        import java.util.Date;
0078:        import java.util.Enumeration;
0079:        import java.util.Vector;
0080:        import java.util.Stack;
0081:        import java.util.StringTokenizer;
0082:        import java.util.Locale;
0083:        import java.util.Hashtable;
0084:        import java.util.Calendar;
0085:        import java.util.TimeZone;
0086:        import java.text.ParseException;
0087:        import java.text.SimpleDateFormat;
0088:        import java.security.MessageDigest;
0089:        import java.security.NoSuchAlgorithmException;
0090:        import org.w3c.dom.Node;
0091:        import org.w3c.dom.NodeList;
0092:        import org.w3c.dom.Element;
0093:        import org.w3c.dom.Document;
0094:        import org.xml.sax.InputSource;
0095:        import javax.servlet.RequestDispatcher;
0096:        import javax.servlet.ServletException;
0097:        import javax.servlet.ServletContext;
0098:        import javax.servlet.ServletOutputStream;
0099:        import javax.servlet.http.HttpServlet;
0100:        import javax.servlet.http.HttpServletRequest;
0101:        import javax.servlet.http.HttpServletResponse;
0102:        import javax.xml.parsers.DocumentBuilder;
0103:        import javax.xml.parsers.DocumentBuilderFactory;
0104:        import javax.xml.parsers.ParserConfigurationException;
0105:        import javax.naming.NamingException;
0106:        import javax.naming.InitialContext;
0107:        import javax.naming.Context;
0108:        import javax.naming.NamingEnumeration;
0109:        import javax.naming.NameClassPair;
0110:        import javax.naming.directory.DirContext;
0111:        import javax.naming.directory.Attribute;
0112:        import javax.naming.directory.Attributes;
0113:        import org.apache.naming.resources.Resource;
0114:        import org.apache.naming.resources.ResourceAttributes;
0115:        import org.apache.catalina.util.MD5Encoder;
0116:        import org.apache.catalina.util.StringManager;
0117:        import org.apache.catalina.util.XMLWriter;
0118:        import org.apache.catalina.util.DOMWriter;
0119:        import org.apache.catalina.util.RequestUtil;
0120:
0121:        /**
0122:         * Servlet which adds support for WebDAV level 2. All the basic HTTP requests
0123:         * are handled by the DefaultServlet.
0124:         *
0125:         * @author Remy Maucherat
0126:         * @version $Revision: 1.28 $ $Date: 2002/04/01 18:12:38 $
0127:         */
0128:
0129:        public class WebdavServlet extends DefaultServlet {
0130:
0131:            // -------------------------------------------------------------- Constants
0132:
0133:            private static final String METHOD_HEAD = "HEAD";
0134:            private static final String METHOD_PROPFIND = "PROPFIND";
0135:            private static final String METHOD_PROPPATCH = "PROPPATCH";
0136:            private static final String METHOD_MKCOL = "MKCOL";
0137:            private static final String METHOD_COPY = "COPY";
0138:            private static final String METHOD_MOVE = "MOVE";
0139:            private static final String METHOD_LOCK = "LOCK";
0140:            private static final String METHOD_UNLOCK = "UNLOCK";
0141:
0142:            /**
0143:             * Default depth is infite.
0144:             */
0145:            private static final int INFINITY = 3; // To limit tree browsing a bit
0146:
0147:            /**
0148:             * PROPFIND - Specify a property mask.
0149:             */
0150:            private static final int FIND_BY_PROPERTY = 0;
0151:
0152:            /**
0153:             * PROPFIND - Display all properties.
0154:             */
0155:            private static final int FIND_ALL_PROP = 1;
0156:
0157:            /**
0158:             * PROPFIND - Return property names.
0159:             */
0160:            private static final int FIND_PROPERTY_NAMES = 2;
0161:
0162:            /**
0163:             * Create a new lock.
0164:             */
0165:            private static final int LOCK_CREATION = 0;
0166:
0167:            /**
0168:             * Refresh lock.
0169:             */
0170:            private static final int LOCK_REFRESH = 1;
0171:
0172:            /**
0173:             * Default lock timeout value.
0174:             */
0175:            private static final int DEFAULT_TIMEOUT = 3600;
0176:
0177:            /**
0178:             * Maximum lock timeout.
0179:             */
0180:            private static final int MAX_TIMEOUT = 604800;
0181:
0182:            /**
0183:             * Default namespace.
0184:             */
0185:            protected static final String DEFAULT_NAMESPACE = "DAV:";
0186:
0187:            /**
0188:             * Simple date format for the creation date ISO representation (partial).
0189:             */
0190:            protected static final SimpleDateFormat creationDateFormat = new SimpleDateFormat(
0191:                    "yyyy-MM-dd'T'HH:mm:ss'Z'");
0192:
0193:            static {
0194:                creationDateFormat.setTimeZone(TimeZone.getTimeZone("GMT"));
0195:            }
0196:
0197:            // ----------------------------------------------------- Instance Variables
0198:
0199:            /**
0200:             * Repository of the locks put on single resources.
0201:             * <p>
0202:             * Key : path <br>
0203:             * Value : LockInfo
0204:             */
0205:            private Hashtable resourceLocks = new Hashtable();
0206:
0207:            /**
0208:             * Repository of the lock-null resources.
0209:             * <p>
0210:             * Key : path of the collection containing the lock-null resource<br>
0211:             * Value : Vector of lock-null resource which are members of the
0212:             * collection. Each element of the Vector is the path associated with
0213:             * the lock-null resource.
0214:             */
0215:            private Hashtable lockNullResources = new Hashtable();
0216:
0217:            /**
0218:             * Vector of the heritable locks.
0219:             * <p>
0220:             * Key : path <br>
0221:             * Value : LockInfo
0222:             */
0223:            private Vector collectionLocks = new Vector();
0224:
0225:            /**
0226:             * Secret information used to generate reasonably secure lock ids.
0227:             */
0228:            private String secret = "catalina";
0229:
0230:            // --------------------------------------------------------- Public Methods
0231:
0232:            /**
0233:             * Initialize this servlet.
0234:             */
0235:            public void init() throws ServletException {
0236:
0237:                super .init();
0238:
0239:                String value = null;
0240:                try {
0241:                    value = getServletConfig().getInitParameter("secret");
0242:                    if (value != null)
0243:                        secret = value;
0244:                } catch (Throwable t) {
0245:                    ;
0246:                }
0247:
0248:            }
0249:
0250:            // ------------------------------------------------------ Protected Methods
0251:
0252:            /**
0253:             * Return JAXP document builder instance.
0254:             */
0255:            protected DocumentBuilder getDocumentBuilder()
0256:                    throws ServletException {
0257:                DocumentBuilder documentBuilder = null;
0258:                try {
0259:                    documentBuilder = DocumentBuilderFactory.newInstance()
0260:                            .newDocumentBuilder();
0261:                } catch (ParserConfigurationException e) {
0262:                    throw new ServletException(sm
0263:                            .getString("webdavservlet.jaxpfailed"));
0264:                }
0265:                return documentBuilder;
0266:            }
0267:
0268:            /**
0269:             * Handles the special WebDAV methods.
0270:             */
0271:            protected void service(HttpServletRequest req,
0272:                    HttpServletResponse resp) throws ServletException,
0273:                    IOException {
0274:
0275:                String method = req.getMethod();
0276:
0277:                if (debug > 0) {
0278:                    String path = getRelativePath(req);
0279:                    System.out.println("[" + method + "] " + path);
0280:                }
0281:
0282:                if (method.equals(METHOD_PROPFIND)) {
0283:                    doPropfind(req, resp);
0284:                } else if (method.equals(METHOD_PROPPATCH)) {
0285:                    doProppatch(req, resp);
0286:                } else if (method.equals(METHOD_MKCOL)) {
0287:                    doMkcol(req, resp);
0288:                } else if (method.equals(METHOD_COPY)) {
0289:                    doCopy(req, resp);
0290:                } else if (method.equals(METHOD_MOVE)) {
0291:                    doMove(req, resp);
0292:                } else if (method.equals(METHOD_LOCK)) {
0293:                    doLock(req, resp);
0294:                } else if (method.equals(METHOD_UNLOCK)) {
0295:                    doUnlock(req, resp);
0296:                } else {
0297:                    // DefaultServlet processing
0298:                    super .service(req, resp);
0299:                }
0300:
0301:            }
0302:
0303:            /**
0304:             * Check if the conditions specified in the optional If headers are
0305:             * satisfied.
0306:             *
0307:             * @param request The servlet request we are processing
0308:             * @param response The servlet response we are creating
0309:             * @param resourceInfo File object
0310:             * @return boolean true if the resource meets all the specified conditions,
0311:             * and false if any of the conditions is not satisfied, in which case
0312:             * request processing is stopped
0313:             */
0314:            protected boolean checkIfHeaders(HttpServletRequest request,
0315:                    HttpServletResponse response, ResourceInfo resourceInfo)
0316:                    throws IOException {
0317:
0318:                if (!super .checkIfHeaders(request, response, resourceInfo))
0319:                    return false;
0320:
0321:                // TODO : Checking the WebDAV If header
0322:                return true;
0323:
0324:            }
0325:
0326:            /**
0327:             * OPTIONS Method.
0328:             */
0329:            protected void doOptions(HttpServletRequest req,
0330:                    HttpServletResponse resp) throws ServletException,
0331:                    IOException {
0332:
0333:                String path = getRelativePath(req);
0334:
0335:                resp.addHeader("DAV", "1,2");
0336:                String methodsAllowed = null;
0337:
0338:                // Retrieve the resources
0339:                DirContext resources = getResources();
0340:
0341:                if (resources == null) {
0342:                    resp
0343:                            .sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
0344:                    return;
0345:                }
0346:
0347:                boolean exists = true;
0348:                Object object = null;
0349:                try {
0350:                    object = resources.lookup(path);
0351:                } catch (NamingException e) {
0352:                    exists = false;
0353:                }
0354:
0355:                if (!exists) {
0356:                    methodsAllowed = "OPTIONS, MKCOL, PUT, LOCK";
0357:                    resp.addHeader("Allow", methodsAllowed);
0358:                    return;
0359:                }
0360:
0361:                methodsAllowed = "OPTIONS, GET, HEAD, POST, DELETE, TRACE, "
0362:                        + "PROPFIND, PROPPATCH, COPY, MOVE, LOCK, UNLOCK";
0363:                if (!(object instanceof  DirContext)) {
0364:                    methodsAllowed += ", PUT";
0365:                }
0366:
0367:                resp.addHeader("Allow", methodsAllowed);
0368:
0369:                resp.addHeader("MS-Author-Via", "DAV");
0370:
0371:            }
0372:
0373:            /**
0374:             * PROPFIND Method.
0375:             */
0376:            protected void doPropfind(HttpServletRequest req, HttpServletResponse resp)
0377:        throws ServletException, IOException {
0378:
0379:        if (!listings) {
0380:            resp.sendError(WebdavStatus.SC_METHOD_NOT_ALLOWED);
0381:            return;
0382:        }
0383:
0384:        String path = getRelativePath(req);
0385:        if (path.endsWith("/"))
0386:            path = path.substring(0, path.length() - 1);
0387:
0388:        if ((path.toUpperCase().startsWith("/WEB-INF")) ||
0389:            (path.toUpperCase().startsWith("/META-INF"))) {
0390:            resp.sendError(WebdavStatus.SC_FORBIDDEN);
0391:            return;
0392:        }
0393:
0394:        // Properties which are to be displayed.
0395:        Vector properties = null;
0396:        // Propfind depth
0397:        int depth = INFINITY;
0398:        // Propfind type
0399:        int type = FIND_ALL_PROP;
0400:
0401:        String depthStr = req.getHeader("Depth");
0402:
0403:        if (depthStr == null) {
0404:            depth = INFINITY;
0405:        } else {
0406:            if (depthStr.equals("0")) {
0407:                depth = 0;
0408:            } else if (depthStr.equals("1")) {
0409:                depth = 1;
0410:            } else if (depthStr.equals("infinity")) {
0411:                depth = INFINITY;
0412:            }
0413:        }
0414:
0415:        Node propNode = null;
0416:
0417:        DocumentBuilder documentBuilder = getDocumentBuilder();
0418:
0419:        try {
0420:            Document document = documentBuilder.parse
0421:                (new InputSource(req.getInputStream()));
0422:
0423:            // Get the root element of the document
0424:            Element rootElement = document.getDocumentElement();
0425:            NodeList childList = rootElement.getChildNodes();
0426:
0427:            for (int i=0; i < childList.getLength(); i++) {
0428:                Node currentNode = childList.item(i);
0429:                switch (currentNode.getNodeType()) {
0430:                case Node.TEXT_NODE:
0431:                    break;
0432:                case Node.ELEMENT_NODE:
0433:                    if (currentNode.getNodeName().endsWith("prop")) {
0434:                        type = FIND_BY_PROPERTY;
0435:                        propNode = currentNode;
0436:                    }
0437:                    if (currentNode.getNodeName().endsWith("propname")) {
0438:                        type = FIND_PROPERTY_NAMES;
0439:                    }
0440:                    if (currentNode.getNodeName().endsWith("allprop")) {
0441:                        type = FIND_ALL_PROP;
0442:                    }
0443:                    break;
0444:                }
0445:            }
0446:        } catch(Exception e) {
0447:            // Most likely there was no content : we use the defaults.
0448:            // TODO : Enhance that !
0449:        }
0450:
0451:        if (type == FIND_BY_PROPERTY) {
0452:            properties = new Vector();
0453:            NodeList childList = propNode.getChildNodes();
0454:
0455:            for (int i=0; i < childList.getLength(); i++) {
0456:                Node currentNode = childList.item(i);
0457:                switch (currentNode.getNodeType()) {
0458:                case Node.TEXT_NODE:
0459:                    break;
0460:                case Node.ELEMENT_NODE:
0461:                    String nodeName = currentNode.getNodeName();
0462:                    String propertyName = null;
0463:                    if (nodeName.indexOf(':') != -1) {
0464:                        propertyName = nodeName.substring
0465:                            (nodeName.indexOf(':') + 1);
0466:                    } else {
0467:                        propertyName = nodeName;
0468:                    }
0469:                    // href is a live property which is handled differently
0470:                    properties.addElement(propertyName);
0471:                    break;
0472:                }
0473:            }
0474:
0475:        }
0476:
0477:        // Retrieve the resources
0478:        DirContext resources = getResources();
0479:
0480:        if (resources == null) {
0481:            resp.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
0482:            return;
0483:        }
0484:
0485:        boolean exists = true;
0486:        Object object = null;
0487:        try {
0488:            object = resources.lookup(path);
0489:        } catch (NamingException e) {
0490:            exists = false;
0491:            int slash = path.lastIndexOf('/');
0492:            if (slash != -1) {
0493:                String parentPath = path.substring(0, slash);
0494:                Vector currentLockNullResources =
0495:                    (Vector) lockNullResources.get(parentPath);
0496:                if (currentLockNullResources != null) {
0497:                    Enumeration lockNullResourcesList =
0498:                        currentLockNullResources.elements();
0499:                    while (lockNullResourcesList.hasMoreElements()) {
0500:                        String lockNullPath = (String)
0501:                            lockNullResourcesList.nextElement();
0502:                        if (lockNullPath.equals(path)) {
0503:                            resp.setStatus(WebdavStatus.SC_MULTI_STATUS);
0504:                            resp.setContentType("text/xml; charset=UTF-8");
0505:                            // Create multistatus object
0506:                            XMLWriter generatedXML = 
0507:                                new XMLWriter(resp.getWriter());
0508:                            generatedXML.writeXMLHeader();
0509:                            generatedXML.writeElement
0510:                                (null, "multistatus"
0511:                                 + generateNamespaceDeclarations(),
0512:                                 XMLWriter.OPENING);
0513:                            parseLockNullProperties
0514:                                (req, generatedXML, lockNullPath, type,
0515:                                 properties);
0516:                            generatedXML.writeElement(null, "multistatus",
0517:                                                      XMLWriter.CLOSING);
0518:                            generatedXML.sendData();
0519:                            return;
0520:                        }
0521:                    }
0522:                }
0523:            }
0524:        }
0525:
0526:        if (!exists) {
0527:            resp.sendError(HttpServletResponse.SC_NOT_FOUND, path);
0528:            return;
0529:        }
0530:
0531:        resp.setStatus(WebdavStatus.SC_MULTI_STATUS);
0532:
0533:        resp.setContentType("text/xml; charset=UTF-8");
0534:
0535:        // Create multistatus object
0536:        XMLWriter generatedXML = new XMLWriter(resp.getWriter());
0537:        generatedXML.writeXMLHeader();
0538:
0539:        generatedXML.writeElement(null, "multistatus"
0540:                                  + generateNamespaceDeclarations(),
0541:                                  XMLWriter.OPENING);
0542:
0543:        if (depth == 0) {
0544:            parseProperties(req, resources, generatedXML, path, type,
0545:                            properties);
0546:        } else {
0547:            // The stack always contains the object of the current level
0548:            Stack stack = new Stack();
0549:            stack.push(path);
0550:
0551:            // Stack of the objects one level below
0552:            Stack stackBelow = new Stack();
0553:
0554:            while ((!stack.isEmpty()) && (depth >= 0)) {
0555:
0556:                String currentPath = (String) stack.pop();
0557:                parseProperties(req, resources, generatedXML, currentPath,
0558:                                type, properties);
0559:
0560:                try {
0561:                    object = resources.lookup(currentPath);
0562:                } catch (NamingException e) {
0563:                    continue;
0564:                }
0565:
0566:                if ((object instanceof  DirContext) && (depth > 0)) {
0567:
0568:                    try {
0569:                        NamingEnumeration enum = resources.list(currentPath);
0570:                        while (enum.hasMoreElements()) {
0571:                            NameClassPair ncPair =
0572:                                (NameClassPair) enum.nextElement();
0573:                            String newPath = currentPath;
0574:                            if (!(newPath.endsWith("/")))
0575:                                newPath += "/";
0576:                            newPath += ncPair.getName();
0577:                            stackBelow.push(newPath);
0578:                        }
0579:                    } catch (NamingException e) {
0580:                        resp.sendError
0581:                            (HttpServletResponse.SC_INTERNAL_SERVER_ERROR,
0582:                             path);
0583:                        return;
0584:                    }
0585:
0586:                    // Displaying the lock-null resources present in that
0587:                    // collection
0588:                    String lockPath = currentPath;
0589:                    if (lockPath.endsWith("/"))
0590:                        lockPath = 
0591:                            lockPath.substring(0, lockPath.length() - 1);
0592:                    Vector currentLockNullResources =
0593:                        (Vector) lockNullResources.get(lockPath);
0594:                    if (currentLockNullResources != null) {
0595:                        Enumeration lockNullResourcesList =
0596:                            currentLockNullResources.elements();
0597:                        while (lockNullResourcesList.hasMoreElements()) {
0598:                            String lockNullPath = (String)
0599:                                lockNullResourcesList.nextElement();
0600:                            parseLockNullProperties
0601:                                (req, generatedXML, lockNullPath, type,
0602:                                 properties);
0603:                        }
0604:                    }
0605:
0606:                }
0607:
0608:                if (stack.isEmpty()) {
0609:                    depth--;
0610:                    stack = stackBelow;
0611:                    stackBelow = new Stack();
0612:                }
0613:
0614:                generatedXML.sendData();
0615:
0616:            }
0617:        }
0618:
0619:        generatedXML.writeElement(null, "multistatus",
0620:                                  XMLWriter.CLOSING);
0621:
0622:        generatedXML.sendData();
0623:
0624:    }
0625:
0626:            /**
0627:             * PROPPATCH Method.
0628:             */
0629:            protected void doProppatch(HttpServletRequest req,
0630:                    HttpServletResponse resp) throws ServletException,
0631:                    IOException {
0632:
0633:                if (readOnly) {
0634:                    resp.sendError(WebdavStatus.SC_FORBIDDEN);
0635:                    return;
0636:                }
0637:
0638:                if (isLocked(req)) {
0639:                    resp.sendError(WebdavStatus.SC_LOCKED);
0640:                    return;
0641:                }
0642:
0643:                resp.sendError(HttpServletResponse.SC_METHOD_NOT_ALLOWED);
0644:
0645:            }
0646:
0647:            /**
0648:             * MKCOL Method.
0649:             */
0650:            protected void doMkcol(HttpServletRequest req,
0651:                    HttpServletResponse resp) throws ServletException,
0652:                    IOException {
0653:
0654:                if (readOnly) {
0655:                    resp.sendError(WebdavStatus.SC_FORBIDDEN);
0656:                    return;
0657:                }
0658:
0659:                if (isLocked(req)) {
0660:                    resp.sendError(WebdavStatus.SC_LOCKED);
0661:                    return;
0662:                }
0663:
0664:                String path = getRelativePath(req);
0665:
0666:                if ((path.toUpperCase().startsWith("/WEB-INF"))
0667:                        || (path.toUpperCase().startsWith("/META-INF"))) {
0668:                    resp.sendError(WebdavStatus.SC_FORBIDDEN);
0669:                    return;
0670:                }
0671:
0672:                // Retrieve the resources
0673:                DirContext resources = getResources();
0674:
0675:                if (resources == null) {
0676:                    resp
0677:                            .sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
0678:                    return;
0679:                }
0680:
0681:                boolean exists = true;
0682:                Object object = null;
0683:                try {
0684:                    object = resources.lookup(path);
0685:                } catch (NamingException e) {
0686:                    exists = false;
0687:                }
0688:
0689:                // Can't create a collection if a resource already exists at the given
0690:                // path
0691:                if (exists) {
0692:                    resp.sendError(WebdavStatus.SC_METHOD_NOT_ALLOWED);
0693:                    return;
0694:                }
0695:
0696:                boolean result = true;
0697:                try {
0698:                    resources.createSubcontext(path);
0699:                } catch (NamingException e) {
0700:                    result = false;
0701:                }
0702:
0703:                if (!result) {
0704:                    resp.sendError(WebdavStatus.SC_CONFLICT, WebdavStatus
0705:                            .getStatusText(WebdavStatus.SC_CONFLICT));
0706:                } else {
0707:                    resp.setStatus(WebdavStatus.SC_CREATED);
0708:                    // Removing any lock-null resource which would be present
0709:                    lockNullResources.remove(path);
0710:                }
0711:
0712:            }
0713:
0714:            /**
0715:             * DELETE Method.
0716:             */
0717:            protected void doDelete(HttpServletRequest req,
0718:                    HttpServletResponse resp) throws ServletException,
0719:                    IOException {
0720:
0721:                if (readOnly) {
0722:                    resp.sendError(WebdavStatus.SC_FORBIDDEN);
0723:                    return;
0724:                }
0725:
0726:                if (isLocked(req)) {
0727:                    resp.sendError(WebdavStatus.SC_LOCKED);
0728:                    return;
0729:                }
0730:
0731:                deleteResource(req, resp);
0732:
0733:            }
0734:
0735:            /**
0736:             * Process a POST request for the specified resource.
0737:             *
0738:             * @param request The servlet request we are processing
0739:             * @param response The servlet response we are creating
0740:             *
0741:             * @exception IOException if an input/output error occurs
0742:             * @exception ServletException if a servlet-specified error occurs
0743:             */
0744:            protected void doPut(HttpServletRequest req,
0745:                    HttpServletResponse resp) throws ServletException,
0746:                    IOException {
0747:
0748:                if (isLocked(req)) {
0749:                    resp.sendError(WebdavStatus.SC_LOCKED);
0750:                    return;
0751:                }
0752:
0753:                super .doPut(req, resp);
0754:
0755:                String path = getRelativePath(req);
0756:
0757:                // Removing any lock-null resource which would be present
0758:                lockNullResources.remove(path);
0759:
0760:            }
0761:
0762:            /**
0763:             * COPY Method.
0764:             */
0765:            protected void doCopy(HttpServletRequest req,
0766:                    HttpServletResponse resp) throws ServletException,
0767:                    IOException {
0768:
0769:                if (readOnly) {
0770:                    resp.sendError(WebdavStatus.SC_FORBIDDEN);
0771:                    return;
0772:                }
0773:
0774:                copyResource(req, resp);
0775:
0776:            }
0777:
0778:            /**
0779:             * MOVE Method.
0780:             */
0781:            protected void doMove(HttpServletRequest req,
0782:                    HttpServletResponse resp) throws ServletException,
0783:                    IOException {
0784:
0785:                if (readOnly) {
0786:                    resp.sendError(WebdavStatus.SC_FORBIDDEN);
0787:                    return;
0788:                }
0789:
0790:                if (isLocked(req)) {
0791:                    resp.sendError(WebdavStatus.SC_LOCKED);
0792:                    return;
0793:                }
0794:
0795:                String path = getRelativePath(req);
0796:
0797:                if (copyResource(req, resp)) {
0798:                    deleteResource(path, req, resp);
0799:                }
0800:
0801:            }
0802:
0803:            /**
0804:             * LOCK Method.
0805:             */
0806:            protected void doLock(HttpServletRequest req,
0807:                    HttpServletResponse resp) throws ServletException,
0808:                    IOException {
0809:
0810:                if (readOnly) {
0811:                    resp.sendError(WebdavStatus.SC_FORBIDDEN);
0812:                    return;
0813:                }
0814:
0815:                if (isLocked(req)) {
0816:                    resp.sendError(WebdavStatus.SC_LOCKED);
0817:                    return;
0818:                }
0819:
0820:                LockInfo lock = new LockInfo();
0821:
0822:                // Parsing lock request
0823:
0824:                // Parsing depth header
0825:
0826:                String depthStr = req.getHeader("Depth");
0827:
0828:                if (depthStr == null) {
0829:                    lock.depth = INFINITY;
0830:                } else {
0831:                    if (depthStr.equals("0")) {
0832:                        lock.depth = 0;
0833:                    } else {
0834:                        lock.depth = INFINITY;
0835:                    }
0836:                }
0837:
0838:                // Parsing timeout header
0839:
0840:                int lockDuration = DEFAULT_TIMEOUT;
0841:                String lockDurationStr = req.getHeader("Timeout");
0842:                if (lockDurationStr == null) {
0843:                    lockDuration = DEFAULT_TIMEOUT;
0844:                } else {
0845:                    if (lockDurationStr.startsWith("Second-")) {
0846:                        lockDuration = (new Integer(lockDurationStr
0847:                                .substring(7))).intValue();
0848:                    } else {
0849:                        if (lockDurationStr.equalsIgnoreCase("infinity")) {
0850:                            lockDuration = MAX_TIMEOUT;
0851:                        } else {
0852:                            try {
0853:                                lockDuration = (new Integer(lockDurationStr))
0854:                                        .intValue();
0855:                            } catch (NumberFormatException e) {
0856:                                lockDuration = MAX_TIMEOUT;
0857:                            }
0858:                        }
0859:                    }
0860:                    if (lockDuration == 0) {
0861:                        lockDuration = DEFAULT_TIMEOUT;
0862:                    }
0863:                    if (lockDuration > MAX_TIMEOUT) {
0864:                        lockDuration = MAX_TIMEOUT;
0865:                    }
0866:                }
0867:                lock.expiresAt = System.currentTimeMillis()
0868:                        + (lockDuration * 1000);
0869:
0870:                int lockRequestType = LOCK_CREATION;
0871:
0872:                Node lockInfoNode = null;
0873:
0874:                DocumentBuilder documentBuilder = getDocumentBuilder();
0875:
0876:                try {
0877:                    Document document = documentBuilder.parse(new InputSource(
0878:                            req.getInputStream()));
0879:
0880:                    // Get the root element of the document
0881:                    Element rootElement = document.getDocumentElement();
0882:                    lockInfoNode = rootElement;
0883:                } catch (Exception e) {
0884:                    lockRequestType = LOCK_REFRESH;
0885:                }
0886:
0887:                if (lockInfoNode != null) {
0888:
0889:                    // Reading lock information
0890:
0891:                    NodeList childList = lockInfoNode.getChildNodes();
0892:                    StringWriter strWriter = null;
0893:                    DOMWriter domWriter = null;
0894:
0895:                    Node lockScopeNode = null;
0896:                    Node lockTypeNode = null;
0897:                    Node lockOwnerNode = null;
0898:
0899:                    for (int i = 0; i < childList.getLength(); i++) {
0900:                        Node currentNode = childList.item(i);
0901:                        switch (currentNode.getNodeType()) {
0902:                        case Node.TEXT_NODE:
0903:                            break;
0904:                        case Node.ELEMENT_NODE:
0905:                            String nodeName = currentNode.getNodeName();
0906:                            if (nodeName.endsWith("lockscope")) {
0907:                                lockScopeNode = currentNode;
0908:                            }
0909:                            if (nodeName.endsWith("locktype")) {
0910:                                lockTypeNode = currentNode;
0911:                            }
0912:                            if (nodeName.endsWith("owner")) {
0913:                                lockOwnerNode = currentNode;
0914:                            }
0915:                            break;
0916:                        }
0917:                    }
0918:
0919:                    if (lockScopeNode != null) {
0920:
0921:                        childList = lockScopeNode.getChildNodes();
0922:                        for (int i = 0; i < childList.getLength(); i++) {
0923:                            Node currentNode = childList.item(i);
0924:                            switch (currentNode.getNodeType()) {
0925:                            case Node.TEXT_NODE:
0926:                                break;
0927:                            case Node.ELEMENT_NODE:
0928:                                String tempScope = currentNode.getNodeName();
0929:                                if (tempScope.indexOf(':') != -1) {
0930:                                    lock.scope = tempScope.substring(tempScope
0931:                                            .indexOf(':') + 1);
0932:                                } else {
0933:                                    lock.scope = tempScope;
0934:                                }
0935:                                break;
0936:                            }
0937:                        }
0938:
0939:                        if (lock.scope == null) {
0940:                            // Bad request
0941:                            resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
0942:                        }
0943:
0944:                    } else {
0945:                        // Bad request
0946:                        resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
0947:                    }
0948:
0949:                    if (lockTypeNode != null) {
0950:
0951:                        childList = lockTypeNode.getChildNodes();
0952:                        for (int i = 0; i < childList.getLength(); i++) {
0953:                            Node currentNode = childList.item(i);
0954:                            switch (currentNode.getNodeType()) {
0955:                            case Node.TEXT_NODE:
0956:                                break;
0957:                            case Node.ELEMENT_NODE:
0958:                                String tempType = currentNode.getNodeName();
0959:                                if (tempType.indexOf(':') != -1) {
0960:                                    lock.type = tempType.substring(tempType
0961:                                            .indexOf(':') + 1);
0962:                                } else {
0963:                                    lock.type = tempType;
0964:                                }
0965:                                break;
0966:                            }
0967:                        }
0968:
0969:                        if (lock.type == null) {
0970:                            // Bad request
0971:                            resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
0972:                        }
0973:
0974:                    } else {
0975:                        // Bad request
0976:                        resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
0977:                    }
0978:
0979:                    if (lockOwnerNode != null) {
0980:
0981:                        childList = lockOwnerNode.getChildNodes();
0982:                        for (int i = 0; i < childList.getLength(); i++) {
0983:                            Node currentNode = childList.item(i);
0984:                            switch (currentNode.getNodeType()) {
0985:                            case Node.TEXT_NODE:
0986:                                lock.owner += currentNode.getNodeValue();
0987:                                break;
0988:                            case Node.ELEMENT_NODE:
0989:                                strWriter = new StringWriter();
0990:                                domWriter = new DOMWriter(strWriter, true);
0991:                                domWriter.print(currentNode);
0992:                                lock.owner += strWriter.toString();
0993:                                break;
0994:                            }
0995:                        }
0996:
0997:                        if (lock.owner == null) {
0998:                            // Bad request
0999:                            resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
1000:                        }
1001:
1002:                    } else {
1003:                        lock.owner = new String();
1004:                    }
1005:
1006:                }
1007:
1008:                String path = getRelativePath(req);
1009:
1010:                lock.path = path;
1011:
1012:                // Retrieve the resources
1013:                DirContext resources = getResources();
1014:
1015:                if (resources == null) {
1016:                    resp
1017:                            .sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
1018:                    return;
1019:                }
1020:
1021:                boolean exists = true;
1022:                Object object = null;
1023:                try {
1024:                    object = resources.lookup(path);
1025:                } catch (NamingException e) {
1026:                    exists = false;
1027:                }
1028:
1029:                Enumeration locksList = null;
1030:
1031:                if (lockRequestType == LOCK_CREATION) {
1032:
1033:                    // Generating lock id
1034:                    String lockTokenStr = req.getServletPath() + "-"
1035:                            + lock.type + "-" + lock.scope + "-"
1036:                            + req.getUserPrincipal() + "-" + lock.depth + "-"
1037:                            + lock.owner + "-" + lock.tokens + "-"
1038:                            + lock.expiresAt + "-" + System.currentTimeMillis()
1039:                            + "-" + secret;
1040:                    String lockToken = md5Encoder.encode(md5Helper
1041:                            .digest(lockTokenStr.getBytes()));
1042:
1043:                    if ((exists) && (object instanceof  DirContext)
1044:                            && (lock.depth == INFINITY)) {
1045:
1046:                        // Locking a collection (and all its member resources)
1047:
1048:                        // Checking if a child resource of this collection is
1049:                        // already locked
1050:                        Vector lockPaths = new Vector();
1051:                        locksList = collectionLocks.elements();
1052:                        while (locksList.hasMoreElements()) {
1053:                            LockInfo currentLock = (LockInfo) locksList
1054:                                    .nextElement();
1055:                            if (currentLock.hasExpired()) {
1056:                                resourceLocks.remove(currentLock.path);
1057:                                continue;
1058:                            }
1059:                            if ((currentLock.path.startsWith(lock.path))
1060:                                    && ((currentLock.isExclusive()) || (lock
1061:                                            .isExclusive()))) {
1062:                                // A child collection of this collection is locked
1063:                                lockPaths.addElement(currentLock.path);
1064:                            }
1065:                        }
1066:                        locksList = resourceLocks.elements();
1067:                        while (locksList.hasMoreElements()) {
1068:                            LockInfo currentLock = (LockInfo) locksList
1069:                                    .nextElement();
1070:                            if (currentLock.hasExpired()) {
1071:                                resourceLocks.remove(currentLock.path);
1072:                                continue;
1073:                            }
1074:                            if ((currentLock.path.startsWith(lock.path))
1075:                                    && ((currentLock.isExclusive()) || (lock
1076:                                            .isExclusive()))) {
1077:                                // A child resource of this collection is locked
1078:                                lockPaths.addElement(currentLock.path);
1079:                            }
1080:                        }
1081:
1082:                        if (!lockPaths.isEmpty()) {
1083:
1084:                            // One of the child paths was locked
1085:                            // We generate a multistatus error report
1086:
1087:                            Enumeration lockPathsList = lockPaths.elements();
1088:
1089:                            resp.setStatus(WebdavStatus.SC_CONFLICT);
1090:
1091:                            XMLWriter generatedXML = new XMLWriter();
1092:                            generatedXML.writeXMLHeader();
1093:
1094:                            generatedXML.writeElement(null, "multistatus"
1095:                                    + generateNamespaceDeclarations(),
1096:                                    XMLWriter.OPENING);
1097:
1098:                            while (lockPathsList.hasMoreElements()) {
1099:                                generatedXML.writeElement(null, "response",
1100:                                        XMLWriter.OPENING);
1101:                                generatedXML.writeElement(null, "href",
1102:                                        XMLWriter.OPENING);
1103:                                generatedXML.writeText((String) lockPathsList
1104:                                        .nextElement());
1105:                                generatedXML.writeElement(null, "href",
1106:                                        XMLWriter.CLOSING);
1107:                                generatedXML.writeElement(null, "status",
1108:                                        XMLWriter.OPENING);
1109:                                generatedXML
1110:                                        .writeText("HTTP/1.1 "
1111:                                                + WebdavStatus.SC_LOCKED
1112:                                                + " "
1113:                                                + WebdavStatus
1114:                                                        .getStatusText(WebdavStatus.SC_LOCKED));
1115:                                generatedXML.writeElement(null, "status",
1116:                                        XMLWriter.CLOSING);
1117:
1118:                                generatedXML.writeElement(null, "response",
1119:                                        XMLWriter.CLOSING);
1120:                            }
1121:
1122:                            generatedXML.writeElement(null, "multistatus",
1123:                                    XMLWriter.CLOSING);
1124:
1125:                            Writer writer = resp.getWriter();
1126:                            writer.write(generatedXML.toString());
1127:                            writer.close();
1128:
1129:                            return;
1130:
1131:                        }
1132:
1133:                        boolean addLock = true;
1134:
1135:                        // Checking if there is already a shared lock on this path
1136:                        locksList = collectionLocks.elements();
1137:                        while (locksList.hasMoreElements()) {
1138:
1139:                            LockInfo currentLock = (LockInfo) locksList
1140:                                    .nextElement();
1141:                            if (currentLock.path.equals(lock.path)) {
1142:
1143:                                if (currentLock.isExclusive()) {
1144:                                    resp.sendError(WebdavStatus.SC_LOCKED);
1145:                                    return;
1146:                                } else {
1147:                                    if (lock.isExclusive()) {
1148:                                        resp.sendError(WebdavStatus.SC_LOCKED);
1149:                                        return;
1150:                                    }
1151:                                }
1152:
1153:                                currentLock.tokens.addElement(lockToken);
1154:                                lock = currentLock;
1155:                                addLock = false;
1156:
1157:                            }
1158:
1159:                        }
1160:
1161:                        if (addLock) {
1162:                            lock.tokens.addElement(lockToken);
1163:                            collectionLocks.addElement(lock);
1164:                        }
1165:
1166:                    } else {
1167:
1168:                        // Locking a single resource
1169:
1170:                        // Retrieving an already existing lock on that resource
1171:                        LockInfo presentLock = (LockInfo) resourceLocks
1172:                                .get(lock.path);
1173:                        if (presentLock != null) {
1174:
1175:                            if ((presentLock.isExclusive())
1176:                                    || (lock.isExclusive())) {
1177:                                // If either lock is exclusive, the lock can't be
1178:                                // granted
1179:                                resp
1180:                                        .sendError(WebdavStatus.SC_PRECONDITION_FAILED);
1181:                                return;
1182:                            } else {
1183:                                presentLock.tokens.addElement(lockToken);
1184:                                lock = presentLock;
1185:                            }
1186:
1187:                        } else {
1188:
1189:                            lock.tokens.addElement(lockToken);
1190:                            resourceLocks.put(lock.path, lock);
1191:
1192:                            // Checking if a resource exists at this path
1193:                            exists = true;
1194:                            try {
1195:                                object = resources.lookup(path);
1196:                            } catch (NamingException e) {
1197:                                exists = false;
1198:                            }
1199:                            if (!exists) {
1200:
1201:                                // "Creating" a lock-null resource
1202:                                int slash = lock.path.lastIndexOf('/');
1203:                                String parentPath = lock.path.substring(0,
1204:                                        slash);
1205:
1206:                                Vector lockNulls = (Vector) lockNullResources
1207:                                        .get(parentPath);
1208:                                if (lockNulls == null) {
1209:                                    lockNulls = new Vector();
1210:                                    lockNullResources
1211:                                            .put(parentPath, lockNulls);
1212:                                }
1213:
1214:                                lockNulls.addElement(lock.path);
1215:
1216:                            }
1217:
1218:                        }
1219:
1220:                    }
1221:
1222:                }
1223:
1224:                if (lockRequestType == LOCK_REFRESH) {
1225:
1226:                    String ifHeader = req.getHeader("If");
1227:                    if (ifHeader == null)
1228:                        ifHeader = "";
1229:
1230:                    // Checking resource locks
1231:
1232:                    LockInfo toRenew = (LockInfo) resourceLocks.get(path);
1233:                    Enumeration tokenList = null;
1234:                    if (lock != null) {
1235:
1236:                        // At least one of the tokens of the locks must have been given
1237:
1238:                        tokenList = toRenew.tokens.elements();
1239:                        while (tokenList.hasMoreElements()) {
1240:                            String token = (String) tokenList.nextElement();
1241:                            if (ifHeader.indexOf(token) != -1) {
1242:                                toRenew.expiresAt = lock.expiresAt;
1243:                                lock = toRenew;
1244:                            }
1245:                        }
1246:
1247:                    }
1248:
1249:                    // Checking inheritable collection locks
1250:
1251:                    Enumeration collectionLocksList = collectionLocks
1252:                            .elements();
1253:                    while (collectionLocksList.hasMoreElements()) {
1254:                        toRenew = (LockInfo) collectionLocksList.nextElement();
1255:                        if (path.equals(toRenew.path)) {
1256:
1257:                            tokenList = toRenew.tokens.elements();
1258:                            while (tokenList.hasMoreElements()) {
1259:                                String token = (String) tokenList.nextElement();
1260:                                if (ifHeader.indexOf(token) != -1) {
1261:                                    toRenew.expiresAt = lock.expiresAt;
1262:                                    lock = toRenew;
1263:                                }
1264:                            }
1265:
1266:                        }
1267:                    }
1268:
1269:                }
1270:
1271:                // Set the status, then generate the XML response containing
1272:                // the lock information
1273:                XMLWriter generatedXML = new XMLWriter();
1274:                generatedXML.writeXMLHeader();
1275:                generatedXML.writeElement(null, "prop"
1276:                        + generateNamespaceDeclarations(), XMLWriter.OPENING);
1277:
1278:                generatedXML.writeElement(null, "lockdiscovery",
1279:                        XMLWriter.OPENING);
1280:
1281:                lock.toXML(generatedXML, true);
1282:
1283:                generatedXML.writeElement(null, "lockdiscovery",
1284:                        XMLWriter.CLOSING);
1285:
1286:                generatedXML.writeElement(null, "prop", XMLWriter.CLOSING);
1287:
1288:                resp.setStatus(WebdavStatus.SC_OK);
1289:                resp.setContentType("text/xml; charset=UTF-8");
1290:                Writer writer = resp.getWriter();
1291:                writer.write(generatedXML.toString());
1292:                writer.close();
1293:
1294:            }
1295:
1296:            /**
1297:             * UNLOCK Method.
1298:             */
1299:            protected void doUnlock(HttpServletRequest req,
1300:                    HttpServletResponse resp) throws ServletException,
1301:                    IOException {
1302:
1303:                if (readOnly) {
1304:                    resp.sendError(WebdavStatus.SC_FORBIDDEN);
1305:                    return;
1306:                }
1307:
1308:                if (isLocked(req)) {
1309:                    resp.sendError(WebdavStatus.SC_LOCKED);
1310:                    return;
1311:                }
1312:
1313:                String path = getRelativePath(req);
1314:
1315:                String lockTokenHeader = req.getHeader("Lock-Token");
1316:                if (lockTokenHeader == null)
1317:                    lockTokenHeader = "";
1318:
1319:                // Checking resource locks
1320:
1321:                LockInfo lock = (LockInfo) resourceLocks.get(path);
1322:                Enumeration tokenList = null;
1323:                if (lock != null) {
1324:
1325:                    // At least one of the tokens of the locks must have been given
1326:
1327:                    tokenList = lock.tokens.elements();
1328:                    while (tokenList.hasMoreElements()) {
1329:                        String token = (String) tokenList.nextElement();
1330:                        if (lockTokenHeader.indexOf(token) != -1) {
1331:                            lock.tokens.removeElement(token);
1332:                        }
1333:                    }
1334:
1335:                    if (lock.tokens.isEmpty()) {
1336:                        resourceLocks.remove(path);
1337:                        // Removing any lock-null resource which would be present
1338:                        lockNullResources.remove(path);
1339:                    }
1340:
1341:                }
1342:
1343:                // Checking inheritable collection locks
1344:
1345:                Enumeration collectionLocksList = collectionLocks.elements();
1346:                while (collectionLocksList.hasMoreElements()) {
1347:                    lock = (LockInfo) collectionLocksList.nextElement();
1348:                    if (path.equals(lock.path)) {
1349:
1350:                        tokenList = lock.tokens.elements();
1351:                        while (tokenList.hasMoreElements()) {
1352:                            String token = (String) tokenList.nextElement();
1353:                            if (lockTokenHeader.indexOf(token) != -1) {
1354:                                lock.tokens.removeElement(token);
1355:                                break;
1356:                            }
1357:                        }
1358:
1359:                        if (lock.tokens.isEmpty()) {
1360:                            collectionLocks.removeElement(lock);
1361:                            // Removing any lock-null resource which would be present
1362:                            lockNullResources.remove(path);
1363:                        }
1364:
1365:                    }
1366:                }
1367:
1368:                resp.setStatus(WebdavStatus.SC_NO_CONTENT);
1369:
1370:            }
1371:
1372:            // -------------------------------------------------------- Private Methods
1373:
1374:            protected String getETagValue(ResourceInfo resourceInfo) {
1375:                return resourceInfo.length + "-" + resourceInfo.date;
1376:            }
1377:
1378:            /**
1379:             * Generate the namespace declarations.
1380:             */
1381:            private String generateNamespaceDeclarations() {
1382:                return " xmlns=\"" + DEFAULT_NAMESPACE + "\"";
1383:            }
1384:
1385:            /**
1386:             * Check to see if a resource is currently write locked. The method
1387:             * will look at the "If" header to make sure the client
1388:             * has give the appropriate lock tokens.
1389:             *
1390:             * @param req Servlet request
1391:             * @return boolean true if the resource is locked (and no appropriate
1392:             * lock token has been found for at least one of the non-shared locks which
1393:             * are present on the resource).
1394:             */
1395:            private boolean isLocked(HttpServletRequest req) {
1396:
1397:                String path = getRelativePath(req);
1398:
1399:                String ifHeader = req.getHeader("If");
1400:                if (ifHeader == null)
1401:                    ifHeader = "";
1402:
1403:                String lockTokenHeader = req.getHeader("Lock-Token");
1404:                if (lockTokenHeader == null)
1405:                    lockTokenHeader = "";
1406:
1407:                return isLocked(path, ifHeader + lockTokenHeader);
1408:
1409:            }
1410:
1411:            /**
1412:             * Check to see if a resource is currently write locked.
1413:             *
1414:             * @param path Path of the resource
1415:             * @param ifHeader "If" HTTP header which was included in the request
1416:             * @return boolean true if the resource is locked (and no appropriate
1417:             * lock token has been found for at least one of the non-shared locks which
1418:             * are present on the resource).
1419:             */
1420:            private boolean isLocked(String path, String ifHeader) {
1421:
1422:                // Checking resource locks
1423:
1424:                LockInfo lock = (LockInfo) resourceLocks.get(path);
1425:                Enumeration tokenList = null;
1426:                if ((lock != null) && (lock.hasExpired())) {
1427:                    resourceLocks.remove(path);
1428:                } else if (lock != null) {
1429:
1430:                    // At least one of the tokens of the locks must have been given
1431:
1432:                    tokenList = lock.tokens.elements();
1433:                    boolean tokenMatch = false;
1434:                    while (tokenList.hasMoreElements()) {
1435:                        String token = (String) tokenList.nextElement();
1436:                        if (ifHeader.indexOf(token) != -1)
1437:                            tokenMatch = true;
1438:                    }
1439:                    if (!tokenMatch)
1440:                        return true;
1441:
1442:                }
1443:
1444:                // Checking inheritable collection locks
1445:
1446:                Enumeration collectionLocksList = collectionLocks.elements();
1447:                while (collectionLocksList.hasMoreElements()) {
1448:                    lock = (LockInfo) collectionLocksList.nextElement();
1449:                    if (lock.hasExpired()) {
1450:                        collectionLocks.removeElement(lock);
1451:                    } else if (path.startsWith(lock.path)) {
1452:
1453:                        tokenList = lock.tokens.elements();
1454:                        boolean tokenMatch = false;
1455:                        while (tokenList.hasMoreElements()) {
1456:                            String token = (String) tokenList.nextElement();
1457:                            if (ifHeader.indexOf(token) != -1)
1458:                                tokenMatch = true;
1459:                        }
1460:                        if (!tokenMatch)
1461:                            return true;
1462:
1463:                    }
1464:                }
1465:
1466:                return false;
1467:
1468:            }
1469:
1470:            /**
1471:             * Copy a resource.
1472:             *
1473:             * @param req Servlet request
1474:             * @param resp Servlet response
1475:             * @return boolean true if the copy is successful
1476:             */
1477:            private boolean copyResource(HttpServletRequest req,
1478:                    HttpServletResponse resp) throws ServletException,
1479:                    IOException {
1480:
1481:                // Parsing destination header
1482:
1483:                String destinationPath = req.getHeader("Destination");
1484:
1485:                if (destinationPath == null) {
1486:                    resp.sendError(WebdavStatus.SC_BAD_REQUEST);
1487:                    return false;
1488:                }
1489:
1490:                int protocolIndex = destinationPath.indexOf("://");
1491:                if (protocolIndex >= 0) {
1492:                    // if the Destination URL contains the protocol, we can safely
1493:                    // trim everything upto the first "/" character after "://"
1494:                    int firstSeparator = destinationPath.indexOf("/",
1495:                            protocolIndex + 4);
1496:                    if (firstSeparator < 0) {
1497:                        destinationPath = "/";
1498:                    } else {
1499:                        destinationPath = destinationPath
1500:                                .substring(firstSeparator);
1501:                    }
1502:                } else {
1503:                    String hostName = req.getServerName();
1504:                    if ((hostName != null)
1505:                            && (destinationPath.startsWith(hostName))) {
1506:                        destinationPath = destinationPath.substring(hostName
1507:                                .length());
1508:                    }
1509:
1510:                    int portIndex = destinationPath.indexOf(":");
1511:                    if (portIndex >= 0) {
1512:                        destinationPath = destinationPath.substring(portIndex);
1513:                    }
1514:
1515:                    if (destinationPath.startsWith(":")) {
1516:                        int firstSeparator = destinationPath.indexOf("/");
1517:                        if (firstSeparator < 0) {
1518:                            destinationPath = "/";
1519:                        } else {
1520:                            destinationPath = destinationPath
1521:                                    .substring(firstSeparator);
1522:                        }
1523:                    }
1524:                }
1525:
1526:                String contextPath = req.getContextPath();
1527:                if ((contextPath != null)
1528:                        && (destinationPath.startsWith(contextPath))) {
1529:                    destinationPath = destinationPath.substring(contextPath
1530:                            .length());
1531:                }
1532:
1533:                String pathInfo = req.getPathInfo();
1534:                if (pathInfo != null) {
1535:                    String servletPath = req.getServletPath();
1536:                    if ((servletPath != null)
1537:                            && (destinationPath.startsWith(servletPath))) {
1538:                        destinationPath = destinationPath.substring(servletPath
1539:                                .length());
1540:                    }
1541:                }
1542:
1543:                destinationPath = RequestUtil.URLDecode(
1544:                        normalize(destinationPath), "UTF8");
1545:
1546:                if (debug > 0)
1547:                    System.out.println("Dest path :" + destinationPath);
1548:
1549:                if ((destinationPath.toUpperCase().startsWith("/WEB-INF"))
1550:                        || (destinationPath.toUpperCase()
1551:                                .startsWith("/META-INF"))) {
1552:                    resp.sendError(WebdavStatus.SC_FORBIDDEN);
1553:                    return false;
1554:                }
1555:
1556:                String path = getRelativePath(req);
1557:
1558:                if ((path.toUpperCase().startsWith("/WEB-INF"))
1559:                        || (path.toUpperCase().startsWith("/META-INF"))) {
1560:                    resp.sendError(WebdavStatus.SC_FORBIDDEN);
1561:                    return false;
1562:                }
1563:
1564:                if (destinationPath.equals(path)) {
1565:                    resp.sendError(WebdavStatus.SC_FORBIDDEN);
1566:                    return false;
1567:                }
1568:
1569:                // Parsing overwrite header
1570:
1571:                boolean overwrite = true;
1572:                String overwriteHeader = req.getHeader("Overwrite");
1573:
1574:                if (overwriteHeader != null) {
1575:                    if (overwriteHeader.equalsIgnoreCase("T")) {
1576:                        overwrite = true;
1577:                    } else {
1578:                        overwrite = false;
1579:                    }
1580:                }
1581:
1582:                // Overwriting the destination
1583:
1584:                // Retrieve the resources
1585:                DirContext resources = getResources();
1586:
1587:                if (resources == null) {
1588:                    resp
1589:                            .sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
1590:                    return false;
1591:                }
1592:
1593:                boolean exists = true;
1594:                try {
1595:                    resources.lookup(destinationPath);
1596:                } catch (NamingException e) {
1597:                    exists = false;
1598:                }
1599:
1600:                if (overwrite) {
1601:
1602:                    // Delete destination resource, if it exists
1603:                    if (exists) {
1604:                        if (!deleteResource(destinationPath, req, resp)) {
1605:                            return false;
1606:                        } else {
1607:                            resp.setStatus(WebdavStatus.SC_NO_CONTENT);
1608:                        }
1609:                    } else {
1610:                        resp.setStatus(WebdavStatus.SC_CREATED);
1611:                    }
1612:
1613:                } else {
1614:
1615:                    // If the destination exists, then it's a conflict
1616:                    if (exists) {
1617:                        resp.sendError(WebdavStatus.SC_PRECONDITION_FAILED);
1618:                        return false;
1619:                    }
1620:
1621:                }
1622:
1623:                // Copying source to destination
1624:
1625:                Hashtable errorList = new Hashtable();
1626:
1627:                boolean result = copyResource(resources, errorList, path,
1628:                        destinationPath);
1629:
1630:                if ((!result) || (!errorList.isEmpty())) {
1631:
1632:                    sendReport(req, resp, errorList);
1633:                    return false;
1634:
1635:                }
1636:
1637:                // Removing any lock-null resource which would be present at
1638:                // the destination path
1639:                lockNullResources.remove(destinationPath);
1640:
1641:                return true;
1642:
1643:            }
1644:
1645:            /**
1646:             * Copy a collection.
1647:             *
1648:             * @param resources Resources implementation to be used
1649:             * @param errorList Hashtable containing the list of errors which occurred
1650:             * during the copy operation
1651:             * @param source Path of the resource to be copied
1652:             * @param dest Destination path
1653:             */
1654:            private boolean copyResource(DirContext resources, Hashtable errorList,
1655:                                 String source, String dest) {
1656:
1657:        if (debug > 1)
1658:            System.out.println("Copy: " + source + " To: " + dest);
1659:
1660:        Object object = null;
1661:        try {
1662:            object = resources.lookup(source);
1663:        } catch (NamingException e) {
1664:        }
1665:
1666:        if (object instanceof  DirContext) {
1667:
1668:            try {
1669:                resources.createSubcontext(dest);
1670:            } catch (NamingException e) {
1671:                errorList.put
1672:                    (dest, new Integer(WebdavStatus.SC_CONFLICT));
1673:                return false;
1674:            }
1675:
1676:            try {
1677:                NamingEnumeration enum = resources.list(source);
1678:                while (enum.hasMoreElements()) {
1679:                    NameClassPair ncPair = (NameClassPair) enum.nextElement();
1680:                    String childDest = dest;
1681:                    if (!childDest.equals("/"))
1682:                        childDest += "/";
1683:                    childDest += ncPair.getName();
1684:                    String childSrc = source;
1685:                    if (!childSrc.equals("/"))
1686:                        childSrc += "/";
1687:                    childSrc += ncPair.getName();
1688:                    copyResource(resources, errorList, childSrc, childDest);
1689:                }
1690:            } catch (NamingException e) {
1691:                errorList.put
1692:                    (dest, new Integer(WebdavStatus.SC_INTERNAL_SERVER_ERROR));
1693:                return false;
1694:            }
1695:
1696:        } else {
1697:
1698:            if (object instanceof  Resource) {
1699:                try {
1700:                    resources.bind(dest, object);
1701:                } catch (NamingException e) {
1702:                    errorList.put
1703:                        (source,
1704:                         new Integer(WebdavStatus.SC_INTERNAL_SERVER_ERROR));
1705:                    return false;
1706:                }
1707:            } else {
1708:                errorList.put
1709:                    (source,
1710:                     new Integer(WebdavStatus.SC_INTERNAL_SERVER_ERROR));
1711:                return false;
1712:            }
1713:
1714:        }
1715:
1716:        return true;
1717:
1718:    }
1719:
1720:            /**
1721:             * Delete a resource.
1722:             *
1723:             * @param req Servlet request
1724:             * @param resp Servlet response
1725:             * @return boolean true if the copy is successful
1726:             */
1727:            private boolean deleteResource(HttpServletRequest req,
1728:                    HttpServletResponse resp) throws ServletException,
1729:                    IOException {
1730:
1731:                String path = getRelativePath(req);
1732:
1733:                return deleteResource(path, req, resp);
1734:
1735:            }
1736:
1737:            /**
1738:             * Delete a resource.
1739:             *
1740:             * @param path Path of the resource which is to be deleted
1741:             * @param req Servlet request
1742:             * @param resp Servlet response
1743:             */
1744:            private boolean deleteResource(String path, HttpServletRequest req,
1745:                    HttpServletResponse resp) throws ServletException,
1746:                    IOException {
1747:
1748:                if ((path.toUpperCase().startsWith("/WEB-INF"))
1749:                        || (path.toUpperCase().startsWith("/META-INF"))) {
1750:                    resp.sendError(WebdavStatus.SC_FORBIDDEN);
1751:                    return false;
1752:                }
1753:
1754:                String ifHeader = req.getHeader("If");
1755:                if (ifHeader == null)
1756:                    ifHeader = "";
1757:
1758:                String lockTokenHeader = req.getHeader("Lock-Token");
1759:                if (lockTokenHeader == null)
1760:                    lockTokenHeader = "";
1761:
1762:                if (isLocked(path, ifHeader + lockTokenHeader)) {
1763:                    resp.sendError(WebdavStatus.SC_LOCKED);
1764:                    return false;
1765:                }
1766:
1767:                // Retrieve the resources
1768:                DirContext resources = getResources();
1769:
1770:                if (resources == null) {
1771:                    resp
1772:                            .sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
1773:                    return false;
1774:                }
1775:
1776:                boolean exists = true;
1777:                Object object = null;
1778:                try {
1779:                    object = resources.lookup(path);
1780:                } catch (NamingException e) {
1781:                    exists = false;
1782:                }
1783:
1784:                if (!exists) {
1785:                    resp.sendError(WebdavStatus.SC_NOT_FOUND);
1786:                    return false;
1787:                }
1788:
1789:                boolean collection = (object instanceof  DirContext);
1790:
1791:                if (!collection) {
1792:                    try {
1793:                        resources.unbind(path);
1794:                    } catch (NamingException e) {
1795:                        resp.sendError(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
1796:                        return false;
1797:                    }
1798:                } else {
1799:
1800:                    Hashtable errorList = new Hashtable();
1801:
1802:                    deleteCollection(req, resources, path, errorList);
1803:                    try {
1804:                        resources.unbind(path);
1805:                    } catch (NamingException e) {
1806:                        errorList.put(path, new Integer(
1807:                                WebdavStatus.SC_INTERNAL_SERVER_ERROR));
1808:                    }
1809:
1810:                    if (!errorList.isEmpty()) {
1811:
1812:                        sendReport(req, resp, errorList);
1813:                        return false;
1814:
1815:                    }
1816:
1817:                }
1818:
1819:                resp.setStatus(WebdavStatus.SC_NO_CONTENT);
1820:                return true;
1821:
1822:            }
1823:
1824:            /**
1825:             * Deletes a collection.
1826:             *
1827:             * @param resources Resources implementation associated with the context
1828:             * @param path Path to the collection to be deleted
1829:             * @param errorList Contains the list of the errors which occurred
1830:             */
1831:            private void deleteCollection(HttpServletRequest req,
1832:                                  DirContext resources,
1833:                                  String path, Hashtable errorList) {
1834:
1835:        if (debug > 1)
1836:            System.out.println("Delete:" + path);
1837:
1838:        if ((path.toUpperCase().startsWith("/WEB-INF")) ||
1839:            (path.toUpperCase().startsWith("/META-INF"))) {
1840:            errorList.put(path, new Integer(WebdavStatus.SC_FORBIDDEN));
1841:            return;
1842:        }
1843:
1844:        String ifHeader = req.getHeader("If");
1845:        if (ifHeader == null)
1846:            ifHeader = "";
1847:
1848:        String lockTokenHeader = req.getHeader("Lock-Token");
1849:        if (lockTokenHeader == null)
1850:            lockTokenHeader = "";
1851:
1852:        Enumeration enum = null;
1853:        try {
1854:            enum = resources.list(path);
1855:        } catch (NamingException e) {
1856:            errorList.put(path, new Integer
1857:                (WebdavStatus.SC_INTERNAL_SERVER_ERROR));
1858:            return;
1859:        }
1860:
1861:        while (enum.hasMoreElements()) {
1862:            NameClassPair ncPair = (NameClassPair) enum.nextElement();
1863:            String childName = path;
1864:            if (!childName.equals("/"))
1865:                childName += "/";
1866:            childName += ncPair.getName();
1867:
1868:            if (isLocked(childName, ifHeader + lockTokenHeader)) {
1869:
1870:                errorList.put(childName, new Integer(WebdavStatus.SC_LOCKED));
1871:
1872:            } else {
1873:
1874:                try {
1875:                    Object object = resources.lookup(childName);
1876:                    if (object instanceof  DirContext) {
1877:                        deleteCollection(req, resources, childName, errorList);
1878:                    }
1879:
1880:                    try {
1881:                        resources.unbind(childName);
1882:                    } catch (NamingException e) {
1883:                        if (!(object instanceof  DirContext)) {
1884:                            // If it's not a collection, then it's an unknown
1885:                            // error
1886:                            errorList.put
1887:                                (childName, new Integer
1888:                                    (WebdavStatus.SC_INTERNAL_SERVER_ERROR));
1889:                        }
1890:                    }
1891:                } catch (NamingException e) {
1892:                    errorList.put
1893:                        (childName, new Integer
1894:                            (WebdavStatus.SC_INTERNAL_SERVER_ERROR));
1895:                }
1896:            }
1897:
1898:        }
1899:
1900:    }
1901:
1902:            /**
1903:             * Send a multistatus element containing a complete error report to the
1904:             * client.
1905:             *
1906:             * @param req Servlet request
1907:             * @param resp Servlet response
1908:             * @param errorList List of error to be displayed
1909:             */
1910:            private void sendReport(HttpServletRequest req,
1911:                    HttpServletResponse resp, Hashtable errorList)
1912:                    throws ServletException, IOException {
1913:
1914:                resp.setStatus(WebdavStatus.SC_MULTI_STATUS);
1915:
1916:                String absoluteUri = req.getRequestURI();
1917:                String relativePath = getRelativePath(req);
1918:
1919:                XMLWriter generatedXML = new XMLWriter();
1920:                generatedXML.writeXMLHeader();
1921:
1922:                generatedXML.writeElement(null, "multistatus"
1923:                        + generateNamespaceDeclarations(), XMLWriter.OPENING);
1924:
1925:                Enumeration pathList = errorList.keys();
1926:                while (pathList.hasMoreElements()) {
1927:
1928:                    String errorPath = (String) pathList.nextElement();
1929:                    int errorCode = ((Integer) errorList.get(errorPath))
1930:                            .intValue();
1931:
1932:                    generatedXML.writeElement(null, "response",
1933:                            XMLWriter.OPENING);
1934:
1935:                    generatedXML.writeElement(null, "href", XMLWriter.OPENING);
1936:                    String toAppend = errorPath
1937:                            .substring(relativePath.length());
1938:                    if (!toAppend.startsWith("/"))
1939:                        toAppend = "/" + toAppend;
1940:                    generatedXML.writeText(absoluteUri + toAppend);
1941:                    generatedXML.writeElement(null, "href", XMLWriter.CLOSING);
1942:                    generatedXML
1943:                            .writeElement(null, "status", XMLWriter.OPENING);
1944:                    generatedXML.writeText("HTTP/1.1 " + errorCode + " "
1945:                            + WebdavStatus.getStatusText(errorCode));
1946:                    generatedXML
1947:                            .writeElement(null, "status", XMLWriter.CLOSING);
1948:
1949:                    generatedXML.writeElement(null, "response",
1950:                            XMLWriter.CLOSING);
1951:
1952:                }
1953:
1954:                generatedXML.writeElement(null, "multistatus",
1955:                        XMLWriter.CLOSING);
1956:
1957:                Writer writer = resp.getWriter();
1958:                writer.write(generatedXML.toString());
1959:                writer.close();
1960:
1961:            }
1962:
1963:            /**
1964:             * Propfind helper method.
1965:             *
1966:             * @param resources Resources object associated with this context
1967:             * @param generatedXML XML response to the Propfind request
1968:             * @param path Path of the current resource
1969:             * @param type Propfind type
1970:             * @param propertiesVector If the propfind type is find properties by
1971:             * name, then this Vector contains those properties
1972:             */
1973:            private void parseProperties(HttpServletRequest req,
1974:                    DirContext resources, XMLWriter generatedXML, String path,
1975:                    int type, Vector propertiesVector) {
1976:
1977:                // Exclude any resource in the /WEB-INF and /META-INF subdirectories
1978:                // (the "toUpperCase()" avoids problems on Windows systems)
1979:                if (path.toUpperCase().startsWith("/WEB-INF")
1980:                        || path.toUpperCase().startsWith("/META-INF"))
1981:                    return;
1982:
1983:                ResourceInfo resourceInfo = new ResourceInfo(path, resources);
1984:
1985:                generatedXML.writeElement(null, "response", XMLWriter.OPENING);
1986:                String status = new String("HTTP/1.1 " + WebdavStatus.SC_OK
1987:                        + " " + WebdavStatus.getStatusText(WebdavStatus.SC_OK));
1988:
1989:                // Generating href element
1990:                generatedXML.writeElement(null, "href", XMLWriter.OPENING);
1991:
1992:                String href = req.getContextPath();
1993:                if ((href.endsWith("/")) && (path.startsWith("/")))
1994:                    href += path.substring(1);
1995:                else
1996:                    href += path;
1997:                if ((resourceInfo.collection) && (!href.endsWith("/")))
1998:                    href += "/";
1999:
2000:                generatedXML.writeText(rewriteUrl(href));
2001:
2002:                generatedXML.writeElement(null, "href", XMLWriter.CLOSING);
2003:
2004:                String resourceName = path;
2005:                int lastSlash = path.lastIndexOf('/');
2006:                if (lastSlash != -1)
2007:                    resourceName = resourceName.substring(lastSlash + 1);
2008:
2009:                switch (type) {
2010:
2011:                case FIND_ALL_PROP:
2012:
2013:                    generatedXML.writeElement(null, "propstat",
2014:                            XMLWriter.OPENING);
2015:                    generatedXML.writeElement(null, "prop", XMLWriter.OPENING);
2016:
2017:                    generatedXML.writeProperty(null, "creationdate",
2018:                            getISOCreationDate(resourceInfo.creationDate));
2019:                    generatedXML.writeElement(null, "displayname",
2020:                            XMLWriter.OPENING);
2021:                    generatedXML.writeData(resourceName);
2022:                    generatedXML.writeElement(null, "displayname",
2023:                            XMLWriter.CLOSING);
2024:                    generatedXML.writeProperty(null, "getcontentlanguage",
2025:                            Locale.getDefault().toString());
2026:                    if (!resourceInfo.collection) {
2027:                        generatedXML.writeProperty(null, "getlastmodified",
2028:                                resourceInfo.httpDate);
2029:                        generatedXML.writeProperty(null, "getcontentlength",
2030:                                String.valueOf(resourceInfo.length));
2031:                        generatedXML.writeProperty(null, "getcontenttype",
2032:                                getServletContext().getMimeType(
2033:                                        resourceInfo.path));
2034:                        generatedXML.writeProperty(null, "getetag",
2035:                                getETagValue(resourceInfo));
2036:                        generatedXML.writeElement(null, "resourcetype",
2037:                                XMLWriter.NO_CONTENT);
2038:                    } else {
2039:                        generatedXML.writeElement(null, "resourcetype",
2040:                                XMLWriter.OPENING);
2041:                        generatedXML.writeElement(null, "collection",
2042:                                XMLWriter.NO_CONTENT);
2043:                        generatedXML.writeElement(null, "resourcetype",
2044:                                XMLWriter.CLOSING);
2045:                    }
2046:
2047:                    generatedXML.writeProperty(null, "source", "");
2048:
2049:                    String supportedLocks = "<lockentry>"
2050:                            + "<lockscope><exclusive/></lockscope>"
2051:                            + "<locktype><write/></locktype>" + "</lockentry>"
2052:                            + "<lockentry>"
2053:                            + "<lockscope><shared/></lockscope>"
2054:                            + "<locktype><write/></locktype>" + "</lockentry>";
2055:                    generatedXML.writeElement(null, "supportedlock",
2056:                            XMLWriter.OPENING);
2057:                    generatedXML.writeText(supportedLocks);
2058:                    generatedXML.writeElement(null, "supportedlock",
2059:                            XMLWriter.CLOSING);
2060:
2061:                    generateLockDiscovery(path, generatedXML);
2062:
2063:                    generatedXML.writeElement(null, "prop", XMLWriter.CLOSING);
2064:                    generatedXML
2065:                            .writeElement(null, "status", XMLWriter.OPENING);
2066:                    generatedXML.writeText(status);
2067:                    generatedXML
2068:                            .writeElement(null, "status", XMLWriter.CLOSING);
2069:                    generatedXML.writeElement(null, "propstat",
2070:                            XMLWriter.CLOSING);
2071:
2072:                    break;
2073:
2074:                case FIND_PROPERTY_NAMES:
2075:
2076:                    generatedXML.writeElement(null, "propstat",
2077:                            XMLWriter.OPENING);
2078:                    generatedXML.writeElement(null, "prop", XMLWriter.OPENING);
2079:
2080:                    generatedXML.writeElement(null, "creationdate",
2081:                            XMLWriter.NO_CONTENT);
2082:                    generatedXML.writeElement(null, "displayname",
2083:                            XMLWriter.NO_CONTENT);
2084:                    if (!resourceInfo.collection) {
2085:                        generatedXML.writeElement(null, "getcontentlanguage",
2086:                                XMLWriter.NO_CONTENT);
2087:                        generatedXML.writeElement(null, "getcontentlength",
2088:                                XMLWriter.NO_CONTENT);
2089:                        generatedXML.writeElement(null, "getcontenttype",
2090:                                XMLWriter.NO_CONTENT);
2091:                        generatedXML.writeElement(null, "getetag",
2092:                                XMLWriter.NO_CONTENT);
2093:                        generatedXML.writeElement(null, "getlastmodified",
2094:                                XMLWriter.NO_CONTENT);
2095:                    }
2096:                    generatedXML.writeElement(null, "resourcetype",
2097:                            XMLWriter.NO_CONTENT);
2098:                    generatedXML.writeElement(null, "source",
2099:                            XMLWriter.NO_CONTENT);
2100:                    generatedXML.writeElement(null, "lockdiscovery",
2101:                            XMLWriter.NO_CONTENT);
2102:
2103:                    generatedXML.writeElement(null, "prop", XMLWriter.CLOSING);
2104:                    generatedXML
2105:                            .writeElement(null, "status", XMLWriter.OPENING);
2106:                    generatedXML.writeText(status);
2107:                    generatedXML
2108:                            .writeElement(null, "status", XMLWriter.CLOSING);
2109:                    generatedXML.writeElement(null, "propstat",
2110:                            XMLWriter.CLOSING);
2111:
2112:                    break;
2113:
2114:                case FIND_BY_PROPERTY:
2115:
2116:                    Vector propertiesNotFound = new Vector();
2117:
2118:                    // Parse the list of properties
2119:
2120:                    generatedXML.writeElement(null, "propstat",
2121:                            XMLWriter.OPENING);
2122:                    generatedXML.writeElement(null, "prop", XMLWriter.OPENING);
2123:
2124:                    Enumeration properties = propertiesVector.elements();
2125:
2126:                    while (properties.hasMoreElements()) {
2127:
2128:                        String property = (String) properties.nextElement();
2129:
2130:                        if (property.equals("creationdate")) {
2131:                            generatedXML
2132:                                    .writeProperty(
2133:                                            null,
2134:                                            "creationdate",
2135:                                            getISOCreationDate(resourceInfo.creationDate));
2136:                        } else if (property.equals("displayname")) {
2137:                            generatedXML.writeElement(null, "displayname",
2138:                                    XMLWriter.OPENING);
2139:                            generatedXML.writeData(resourceName);
2140:                            generatedXML.writeElement(null, "displayname",
2141:                                    XMLWriter.CLOSING);
2142:                        } else if (property.equals("getcontentlanguage")) {
2143:                            if (resourceInfo.collection) {
2144:                                propertiesNotFound.addElement(property);
2145:                            } else {
2146:                                generatedXML.writeProperty(null,
2147:                                        "getcontentlanguage", Locale
2148:                                                .getDefault().toString());
2149:                            }
2150:                        } else if (property.equals("getcontentlength")) {
2151:                            if (resourceInfo.collection) {
2152:                                propertiesNotFound.addElement(property);
2153:                            } else {
2154:                                generatedXML.writeProperty(null,
2155:                                        "getcontentlength", (String
2156:                                                .valueOf(resourceInfo.length)));
2157:                            }
2158:                        } else if (property.equals("getcontenttype")) {
2159:                            if (resourceInfo.collection) {
2160:                                propertiesNotFound.addElement(property);
2161:                            } else {
2162:                                generatedXML
2163:                                        .writeProperty(
2164:                                                null,
2165:                                                "getcontenttype",
2166:                                                getServletContext()
2167:                                                        .getMimeType(
2168:                                                                resourceInfo.path));
2169:                            }
2170:                        } else if (property.equals("getetag")) {
2171:                            if (resourceInfo.collection) {
2172:                                propertiesNotFound.addElement(property);
2173:                            } else {
2174:                                generatedXML.writeProperty(null, "getetag",
2175:                                        getETagValue(resourceInfo));
2176:                            }
2177:                        } else if (property.equals("getlastmodified")) {
2178:                            if (resourceInfo.collection) {
2179:                                propertiesNotFound.addElement(property);
2180:                            } else {
2181:                                generatedXML.writeProperty(null,
2182:                                        "getlastmodified",
2183:                                        resourceInfo.httpDate);
2184:                            }
2185:                        } else if (property.equals("resourcetype")) {
2186:                            if (resourceInfo.collection) {
2187:                                generatedXML.writeElement(null, "resourcetype",
2188:                                        XMLWriter.OPENING);
2189:                                generatedXML.writeElement(null, "collection",
2190:                                        XMLWriter.NO_CONTENT);
2191:                                generatedXML.writeElement(null, "resourcetype",
2192:                                        XMLWriter.CLOSING);
2193:                            } else {
2194:                                generatedXML.writeElement(null, "resourcetype",
2195:                                        XMLWriter.NO_CONTENT);
2196:                            }
2197:                        } else if (property.equals("source")) {
2198:                            generatedXML.writeProperty(null, "source", "");
2199:                        } else if (property.equals("supportedlock")) {
2200:                            supportedLocks = "<lockentry>"
2201:                                    + "<lockscope><exclusive/></lockscope>"
2202:                                    + "<locktype><write/></locktype>"
2203:                                    + "</lockentry>" + "<lockentry>"
2204:                                    + "<lockscope><shared/></lockscope>"
2205:                                    + "<locktype><write/></locktype>"
2206:                                    + "</lockentry>";
2207:                            generatedXML.writeElement(null, "supportedlock",
2208:                                    XMLWriter.OPENING);
2209:                            generatedXML.writeText(supportedLocks);
2210:                            generatedXML.writeElement(null, "supportedlock",
2211:                                    XMLWriter.CLOSING);
2212:                        } else if (property.equals("lockdiscovery")) {
2213:                            if (!generateLockDiscovery(path, generatedXML))
2214:                                propertiesNotFound.addElement(property);
2215:                        } else {
2216:                            propertiesNotFound.addElement(property);
2217:                        }
2218:
2219:                    }
2220:
2221:                    generatedXML.writeElement(null, "prop", XMLWriter.CLOSING);
2222:                    generatedXML
2223:                            .writeElement(null, "status", XMLWriter.OPENING);
2224:                    generatedXML.writeText(status);
2225:                    generatedXML
2226:                            .writeElement(null, "status", XMLWriter.CLOSING);
2227:                    generatedXML.writeElement(null, "propstat",
2228:                            XMLWriter.CLOSING);
2229:
2230:                    Enumeration propertiesNotFoundList = propertiesNotFound
2231:                            .elements();
2232:
2233:                    if (propertiesNotFoundList.hasMoreElements()) {
2234:
2235:                        status = new String(
2236:                                "HTTP/1.1 "
2237:                                        + WebdavStatus.SC_NOT_FOUND
2238:                                        + " "
2239:                                        + WebdavStatus
2240:                                                .getStatusText(WebdavStatus.SC_NOT_FOUND));
2241:
2242:                        generatedXML.writeElement(null, "propstat",
2243:                                XMLWriter.OPENING);
2244:                        generatedXML.writeElement(null, "prop",
2245:                                XMLWriter.OPENING);
2246:
2247:                        while (propertiesNotFoundList.hasMoreElements()) {
2248:                            generatedXML.writeElement(null,
2249:                                    (String) propertiesNotFoundList
2250:                                            .nextElement(),
2251:                                    XMLWriter.NO_CONTENT);
2252:                        }
2253:
2254:                        generatedXML.writeElement(null, "prop",
2255:                                XMLWriter.CLOSING);
2256:                        generatedXML.writeElement(null, "status",
2257:                                XMLWriter.OPENING);
2258:                        generatedXML.writeText(status);
2259:                        generatedXML.writeElement(null, "status",
2260:                                XMLWriter.CLOSING);
2261:                        generatedXML.writeElement(null, "propstat",
2262:                                XMLWriter.CLOSING);
2263:
2264:                    }
2265:
2266:                    break;
2267:
2268:                }
2269:
2270:                generatedXML.writeElement(null, "response", XMLWriter.CLOSING);
2271:
2272:            }
2273:
2274:            /**
2275:             * Propfind helper method. Dispays the properties of a lock-null resource.
2276:             *
2277:             * @param resources Resources object associated with this context
2278:             * @param generatedXML XML response to the Propfind request
2279:             * @param path Path of the current resource
2280:             * @param type Propfind type
2281:             * @param propertiesVector If the propfind type is find properties by
2282:             * name, then this Vector contains those properties
2283:             */
2284:            private void parseLockNullProperties(HttpServletRequest req,
2285:                    XMLWriter generatedXML, String path, int type,
2286:                    Vector propertiesVector) {
2287:
2288:                // Exclude any resource in the /WEB-INF and /META-INF subdirectories
2289:                // (the "toUpperCase()" avoids problems on Windows systems)
2290:                if (path.toUpperCase().startsWith("/WEB-INF")
2291:                        || path.toUpperCase().startsWith("/META-INF"))
2292:                    return;
2293:
2294:                // Retrieving the lock associated with the lock-null resource
2295:                LockInfo lock = (LockInfo) resourceLocks.get(path);
2296:
2297:                if (lock == null)
2298:                    return;
2299:
2300:                generatedXML.writeElement(null, "response", XMLWriter.OPENING);
2301:                String status = new String("HTTP/1.1 " + WebdavStatus.SC_OK
2302:                        + " " + WebdavStatus.getStatusText(WebdavStatus.SC_OK));
2303:
2304:                // Generating href element
2305:                generatedXML.writeElement(null, "href", XMLWriter.OPENING);
2306:
2307:                String absoluteUri = req.getRequestURI();
2308:                String relativePath = getRelativePath(req);
2309:                String toAppend = path.substring(relativePath.length());
2310:                if (!toAppend.startsWith("/"))
2311:                    toAppend = "/" + toAppend;
2312:
2313:                generatedXML.writeText(rewriteUrl(normalize(absoluteUri
2314:                        + toAppend)));
2315:
2316:                generatedXML.writeElement(null, "href", XMLWriter.CLOSING);
2317:
2318:                String resourceName = path;
2319:                int lastSlash = path.lastIndexOf('/');
2320:                if (lastSlash != -1)
2321:                    resourceName = resourceName.substring(lastSlash + 1);
2322:
2323:                switch (type) {
2324:
2325:                case FIND_ALL_PROP:
2326:
2327:                    generatedXML.writeElement(null, "propstat",
2328:                            XMLWriter.OPENING);
2329:                    generatedXML.writeElement(null, "prop", XMLWriter.OPENING);
2330:
2331:                    generatedXML.writeProperty(null, "creationdate",
2332:                            getISOCreationDate(lock.creationDate.getTime()));
2333:                    generatedXML.writeElement(null, "displayname",
2334:                            XMLWriter.OPENING);
2335:                    generatedXML.writeData(resourceName);
2336:                    generatedXML.writeElement(null, "displayname",
2337:                            XMLWriter.CLOSING);
2338:                    generatedXML.writeProperty(null, "getcontentlanguage",
2339:                            Locale.getDefault().toString());
2340:                    generatedXML.writeProperty(null, "getlastmodified",
2341:                            formats[0].format(lock.creationDate));
2342:                    generatedXML.writeProperty(null, "getcontentlength", String
2343:                            .valueOf(0));
2344:                    generatedXML.writeProperty(null, "getcontenttype", "");
2345:                    generatedXML.writeProperty(null, "getetag", "");
2346:                    generatedXML.writeElement(null, "resourcetype",
2347:                            XMLWriter.OPENING);
2348:                    generatedXML.writeElement(null, "lock-null",
2349:                            XMLWriter.NO_CONTENT);
2350:                    generatedXML.writeElement(null, "resourcetype",
2351:                            XMLWriter.CLOSING);
2352:
2353:                    generatedXML.writeProperty(null, "source", "");
2354:
2355:                    String supportedLocks = "<lockentry>"
2356:                            + "<lockscope><exclusive/></lockscope>"
2357:                            + "<locktype><write/></locktype>" + "</lockentry>"
2358:                            + "<lockentry>"
2359:                            + "<lockscope><shared/></lockscope>"
2360:                            + "<locktype><write/></locktype>" + "</lockentry>";
2361:                    generatedXML.writeElement(null, "supportedlock",
2362:                            XMLWriter.OPENING);
2363:                    generatedXML.writeText(supportedLocks);
2364:                    generatedXML.writeElement(null, "supportedlock",
2365:                            XMLWriter.CLOSING);
2366:
2367:                    generateLockDiscovery(path, generatedXML);
2368:
2369:                    generatedXML.writeElement(null, "prop", XMLWriter.CLOSING);
2370:                    generatedXML
2371:                            .writeElement(null, "status", XMLWriter.OPENING);
2372:                    generatedXML.writeText(status);
2373:                    generatedXML
2374:                            .writeElement(null, "status", XMLWriter.CLOSING);
2375:                    generatedXML.writeElement(null, "propstat",
2376:                            XMLWriter.CLOSING);
2377:
2378:                    break;
2379:
2380:                case FIND_PROPERTY_NAMES:
2381:
2382:                    generatedXML.writeElement(null, "propstat",
2383:                            XMLWriter.OPENING);
2384:                    generatedXML.writeElement(null, "prop", XMLWriter.OPENING);
2385:
2386:                    generatedXML.writeElement(null, "creationdate",
2387:                            XMLWriter.NO_CONTENT);
2388:                    generatedXML.writeElement(null, "displayname",
2389:                            XMLWriter.NO_CONTENT);
2390:                    generatedXML.writeElement(null, "getcontentlanguage",
2391:                            XMLWriter.NO_CONTENT);
2392:                    generatedXML.writeElement(null, "getcontentlength",
2393:                            XMLWriter.NO_CONTENT);
2394:                    generatedXML.writeElement(null, "getcontenttype",
2395:                            XMLWriter.NO_CONTENT);
2396:                    generatedXML.writeElement(null, "getetag",
2397:                            XMLWriter.NO_CONTENT);
2398:                    generatedXML.writeElement(null, "getlastmodified",
2399:                            XMLWriter.NO_CONTENT);
2400:                    generatedXML.writeElement(null, "resourcetype",
2401:                            XMLWriter.NO_CONTENT);
2402:                    generatedXML.writeElement(null, "source",
2403:                            XMLWriter.NO_CONTENT);
2404:                    generatedXML.writeElement(null, "lockdiscovery",
2405:                            XMLWriter.NO_CONTENT);
2406:
2407:                    generatedXML.writeElement(null, "prop", XMLWriter.CLOSING);
2408:                    generatedXML
2409:                            .writeElement(null, "status", XMLWriter.OPENING);
2410:                    generatedXML.writeText(status);
2411:                    generatedXML
2412:                            .writeElement(null, "status", XMLWriter.CLOSING);
2413:                    generatedXML.writeElement(null, "propstat",
2414:                            XMLWriter.CLOSING);
2415:
2416:                    break;
2417:
2418:                case FIND_BY_PROPERTY:
2419:
2420:                    Vector propertiesNotFound = new Vector();
2421:
2422:                    // Parse the list of properties
2423:
2424:                    generatedXML.writeElement(null, "propstat",
2425:                            XMLWriter.OPENING);
2426:                    generatedXML.writeElement(null, "prop", XMLWriter.OPENING);
2427:
2428:                    Enumeration properties = propertiesVector.elements();
2429:
2430:                    while (properties.hasMoreElements()) {
2431:
2432:                        String property = (String) properties.nextElement();
2433:
2434:                        if (property.equals("creationdate")) {
2435:                            generatedXML.writeProperty(null, "creationdate",
2436:                                    getISOCreationDate(lock.creationDate
2437:                                            .getTime()));
2438:                        } else if (property.equals("displayname")) {
2439:                            generatedXML.writeElement(null, "displayname",
2440:                                    XMLWriter.OPENING);
2441:                            generatedXML.writeData(resourceName);
2442:                            generatedXML.writeElement(null, "displayname",
2443:                                    XMLWriter.CLOSING);
2444:                        } else if (property.equals("getcontentlanguage")) {
2445:                            generatedXML.writeProperty(null,
2446:                                    "getcontentlanguage", Locale.getDefault()
2447:                                            .toString());
2448:                        } else if (property.equals("getcontentlength")) {
2449:                            generatedXML.writeProperty(null,
2450:                                    "getcontentlength", (String.valueOf(0)));
2451:                        } else if (property.equals("getcontenttype")) {
2452:                            generatedXML.writeProperty(null, "getcontenttype",
2453:                                    "");
2454:                        } else if (property.equals("getetag")) {
2455:                            generatedXML.writeProperty(null, "getetag", "");
2456:                        } else if (property.equals("getlastmodified")) {
2457:                            generatedXML.writeProperty(null, "getlastmodified",
2458:                                    formats[0].format(lock.creationDate));
2459:                        } else if (property.equals("resourcetype")) {
2460:                            generatedXML.writeElement(null, "resourcetype",
2461:                                    XMLWriter.OPENING);
2462:                            generatedXML.writeElement(null, "lock-null",
2463:                                    XMLWriter.NO_CONTENT);
2464:                            generatedXML.writeElement(null, "resourcetype",
2465:                                    XMLWriter.CLOSING);
2466:                        } else if (property.equals("source")) {
2467:                            generatedXML.writeProperty(null, "source", "");
2468:                        } else if (property.equals("supportedlock")) {
2469:                            supportedLocks = "<lockentry>"
2470:                                    + "<lockscope><exclusive/></lockscope>"
2471:                                    + "<locktype><write/></locktype>"
2472:                                    + "</lockentry>" + "<lockentry>"
2473:                                    + "<lockscope><shared/></lockscope>"
2474:                                    + "<locktype><write/></locktype>"
2475:                                    + "</lockentry>";
2476:                            generatedXML.writeElement(null, "supportedlock",
2477:                                    XMLWriter.OPENING);
2478:                            generatedXML.writeText(supportedLocks);
2479:                            generatedXML.writeElement(null, "supportedlock",
2480:                                    XMLWriter.CLOSING);
2481:                        } else if (property.equals("lockdiscovery")) {
2482:                            if (!generateLockDiscovery(path, generatedXML))
2483:                                propertiesNotFound.addElement(property);
2484:                        } else {
2485:                            propertiesNotFound.addElement(property);
2486:                        }
2487:
2488:                    }
2489:
2490:                    generatedXML.writeElement(null, "prop", XMLWriter.CLOSING);
2491:                    generatedXML
2492:                            .writeElement(null, "status", XMLWriter.OPENING);
2493:                    generatedXML.writeText(status);
2494:                    generatedXML
2495:                            .writeElement(null, "status", XMLWriter.CLOSING);
2496:                    generatedXML.writeElement(null, "propstat",
2497:                            XMLWriter.CLOSING);
2498:
2499:                    Enumeration propertiesNotFoundList = propertiesNotFound
2500:                            .elements();
2501:
2502:                    if (propertiesNotFoundList.hasMoreElements()) {
2503:
2504:                        status = new String(
2505:                                "HTTP/1.1 "
2506:                                        + WebdavStatus.SC_NOT_FOUND
2507:                                        + " "
2508:                                        + WebdavStatus
2509:                                                .getStatusText(WebdavStatus.SC_NOT_FOUND));
2510:
2511:                        generatedXML.writeElement(null, "propstat",
2512:                                XMLWriter.OPENING);
2513:                        generatedXML.writeElement(null, "prop",
2514:                                XMLWriter.OPENING);
2515:
2516:                        while (propertiesNotFoundList.hasMoreElements()) {
2517:                            generatedXML.writeElement(null,
2518:                                    (String) propertiesNotFoundList
2519:                                            .nextElement(),
2520:                                    XMLWriter.NO_CONTENT);
2521:                        }
2522:
2523:                        generatedXML.writeElement(null, "prop",
2524:                                XMLWriter.CLOSING);
2525:                        generatedXML.writeElement(null, "status",
2526:                                XMLWriter.OPENING);
2527:                        generatedXML.writeText(status);
2528:                        generatedXML.writeElement(null, "status",
2529:                                XMLWriter.CLOSING);
2530:                        generatedXML.writeElement(null, "propstat",
2531:                                XMLWriter.CLOSING);
2532:
2533:                    }
2534:
2535:                    break;
2536:
2537:                }
2538:
2539:                generatedXML.writeElement(null, "response", XMLWriter.CLOSING);
2540:
2541:            }
2542:
2543:            /**
2544:             * Print the lock discovery information associated with a path.
2545:             *
2546:             * @param path Path
2547:             * @param generatedXML XML data to which the locks info will be appended
2548:             * @return true if at least one lock was displayed
2549:             */
2550:            private boolean generateLockDiscovery(String path,
2551:                    XMLWriter generatedXML) {
2552:
2553:                LockInfo resourceLock = (LockInfo) resourceLocks.get(path);
2554:                Enumeration collectionLocksList = collectionLocks.elements();
2555:
2556:                boolean wroteStart = false;
2557:
2558:                if (resourceLock != null) {
2559:                    wroteStart = true;
2560:                    generatedXML.writeElement(null, "lockdiscovery",
2561:                            XMLWriter.OPENING);
2562:                    resourceLock.toXML(generatedXML);
2563:                }
2564:
2565:                while (collectionLocksList.hasMoreElements()) {
2566:                    LockInfo currentLock = (LockInfo) collectionLocksList
2567:                            .nextElement();
2568:                    if (path.startsWith(currentLock.path)) {
2569:                        if (!wroteStart) {
2570:                            wroteStart = true;
2571:                            generatedXML.writeElement(null, "lockdiscovery",
2572:                                    XMLWriter.OPENING);
2573:                        }
2574:                        currentLock.toXML(generatedXML);
2575:                    }
2576:                }
2577:
2578:                if (wroteStart) {
2579:                    generatedXML.writeElement(null, "lockdiscovery",
2580:                            XMLWriter.CLOSING);
2581:                } else {
2582:                    return false;
2583:                }
2584:
2585:                return true;
2586:
2587:            }
2588:
2589:            /**
2590:             * Get creation date in ISO format.
2591:             */
2592:            private String getISOCreationDate(long creationDate) {
2593:                StringBuffer creationDateValue = new StringBuffer(
2594:                        creationDateFormat.format(new Date(creationDate)));
2595:                /*
2596:                int offset = Calendar.getInstance().getTimeZone().getRawOffset()
2597:                    / 3600000; // FIXME ?
2598:                if (offset < 0) {
2599:                    creationDateValue.append("-");
2600:                    offset = -offset;
2601:                } else if (offset > 0) {
2602:                    creationDateValue.append("+");
2603:                }
2604:                if (offset != 0) {
2605:                    if (offset < 10)
2606:                        creationDateValue.append("0");
2607:                    creationDateValue.append(offset + ":00");
2608:                } else {
2609:                    creationDateValue.append("Z");
2610:                }
2611:                 */
2612:                return creationDateValue.toString();
2613:            }
2614:
2615:            // --------------------------------------------------  LockInfo Inner Class
2616:
2617:            /**
2618:             * Holds a lock information.
2619:             */
2620:            private class LockInfo {
2621:
2622:                // -------------------------------------------------------- Constructor
2623:
2624:                /**
2625:                 * Constructor.
2626:                 *
2627:                 * @param pathname Path name of the file
2628:                 */
2629:                public LockInfo() {
2630:
2631:                }
2632:
2633:                // ------------------------------------------------- Instance Variables
2634:
2635:                String path = "/";
2636:                String type = "write";
2637:                String scope = "exclusive";
2638:                int depth = 0;
2639:                String owner = "";
2640:                Vector tokens = new Vector();
2641:                long expiresAt = 0;
2642:                Date creationDate = new Date();
2643:
2644:                // ----------------------------------------------------- Public Methods
2645:
2646:                /**
2647:                 * Get a String representation of this lock token.
2648:                 */
2649:                public String toString() {
2650:
2651:                    String result = "Type:" + type + "\n";
2652:                    result += "Scope:" + scope + "\n";
2653:                    result += "Depth:" + depth + "\n";
2654:                    result += "Owner:" + owner + "\n";
2655:                    result += "Expiration:"
2656:                            + formats[0].format(new Date(expiresAt)) + "\n";
2657:                    Enumeration tokensList = tokens.elements();
2658:                    while (tokensList.hasMoreElements()) {
2659:                        result += "Token:" + tokensList.nextElement() + "\n";
2660:                    }
2661:                    return result;
2662:
2663:                }
2664:
2665:                /**
2666:                 * Return true if the lock has expired.
2667:                 */
2668:                public boolean hasExpired() {
2669:                    return (System.currentTimeMillis() > expiresAt);
2670:                }
2671:
2672:                /**
2673:                 * Return true if the lock is exclusive.
2674:                 */
2675:                public boolean isExclusive() {
2676:
2677:                    return (scope.equals("exclusive"));
2678:
2679:                }
2680:
2681:                /**
2682:                 * Get an XML representation of this lock token. This method will
2683:                 * append an XML fragment to the given XML writer.
2684:                 */
2685:                public void toXML(XMLWriter generatedXML) {
2686:                    toXML(generatedXML, false);
2687:                }
2688:
2689:                /**
2690:                 * Get an XML representation of this lock token. This method will
2691:                 * append an XML fragment to the given XML writer.
2692:                 */
2693:                public void toXML(XMLWriter generatedXML, boolean showToken) {
2694:
2695:                    generatedXML.writeElement(null, "activelock",
2696:                            XMLWriter.OPENING);
2697:
2698:                    generatedXML.writeElement(null, "locktype",
2699:                            XMLWriter.OPENING);
2700:                    generatedXML.writeElement(null, type, XMLWriter.NO_CONTENT);
2701:                    generatedXML.writeElement(null, "locktype",
2702:                            XMLWriter.CLOSING);
2703:
2704:                    generatedXML.writeElement(null, "lockscope",
2705:                            XMLWriter.OPENING);
2706:                    generatedXML
2707:                            .writeElement(null, scope, XMLWriter.NO_CONTENT);
2708:                    generatedXML.writeElement(null, "lockscope",
2709:                            XMLWriter.CLOSING);
2710:
2711:                    generatedXML.writeElement(null, "depth", XMLWriter.OPENING);
2712:                    if (depth == INFINITY) {
2713:                        generatedXML.writeText("Infinity");
2714:                    } else {
2715:                        generatedXML.writeText("0");
2716:                    }
2717:                    generatedXML.writeElement(null, "depth", XMLWriter.CLOSING);
2718:
2719:                    generatedXML.writeElement(null, "owner", XMLWriter.OPENING);
2720:                    generatedXML.writeText(owner);
2721:                    generatedXML.writeElement(null, "owner", XMLWriter.CLOSING);
2722:
2723:                    generatedXML.writeElement(null, "timeout",
2724:                            XMLWriter.OPENING);
2725:                    long timeout = (expiresAt - System.currentTimeMillis()) / 1000;
2726:                    generatedXML.writeText("Second-" + timeout);
2727:                    generatedXML.writeElement(null, "timeout",
2728:                            XMLWriter.CLOSING);
2729:
2730:                    generatedXML.writeElement(null, "locktoken",
2731:                            XMLWriter.OPENING);
2732:                    if (showToken) {
2733:                        Enumeration tokensList = tokens.elements();
2734:                        while (tokensList.hasMoreElements()) {
2735:                            generatedXML.writeElement(null, "href",
2736:                                    XMLWriter.OPENING);
2737:                            generatedXML.writeText("opaquelocktoken:"
2738:                                    + tokensList.nextElement());
2739:                            generatedXML.writeElement(null, "href",
2740:                                    XMLWriter.CLOSING);
2741:                        }
2742:                    } else {
2743:                        generatedXML.writeElement(null, "href",
2744:                                XMLWriter.OPENING);
2745:                        generatedXML.writeText("opaquelocktoken:dummytoken");
2746:                        generatedXML.writeElement(null, "href",
2747:                                XMLWriter.CLOSING);
2748:                    }
2749:                    generatedXML.writeElement(null, "locktoken",
2750:                            XMLWriter.CLOSING);
2751:
2752:                    generatedXML.writeElement(null, "activelock",
2753:                            XMLWriter.CLOSING);
2754:
2755:                }
2756:
2757:            }
2758:
2759:            // --------------------------------------------------- Property Inner Class
2760:
2761:            private class Property {
2762:
2763:                public String name;
2764:                public String value;
2765:                public String namespace;
2766:                public String namespaceAbbrev;
2767:                public int status = WebdavStatus.SC_OK;
2768:
2769:            }
2770:
2771:        };
2772:
2773:        // --------------------------------------------------------  WebdavStatus Class
2774:
2775:        /**
2776:         * Wraps the HttpServletResponse class to abstract the
2777:         * specific protocol used.  To support other protocols
2778:         * we would only need to modify this class and the
2779:         * WebDavRetCode classes.
2780:         *
2781:         * @author              Marc Eaddy
2782:         * @version             1.0, 16 Nov 1997
2783:         */
2784:        class WebdavStatus {
2785:
2786:            // ----------------------------------------------------- Instance Variables
2787:
2788:            /**
2789:             * This Hashtable contains the mapping of HTTP and WebDAV
2790:             * status codes to descriptive text.  This is a static
2791:             * variable.
2792:             */
2793:            private static Hashtable mapStatusCodes = new Hashtable();
2794:
2795:            // ------------------------------------------------------ HTTP Status Codes
2796:
2797:            /**
2798:             * Status code (200) indicating the request succeeded normally.
2799:             */
2800:            public static final int SC_OK = HttpServletResponse.SC_OK;
2801:
2802:            /**
2803:             * Status code (201) indicating the request succeeded and created
2804:             * a new resource on the server.
2805:             */
2806:            public static final int SC_CREATED = HttpServletResponse.SC_CREATED;
2807:
2808:            /**
2809:             * Status code (202) indicating that a request was accepted for
2810:             * processing, but was not completed.
2811:             */
2812:            public static final int SC_ACCEPTED = HttpServletResponse.SC_ACCEPTED;
2813:
2814:            /**
2815:             * Status code (204) indicating that the request succeeded but that
2816:             * there was no new information to return.
2817:             */
2818:            public static final int SC_NO_CONTENT = HttpServletResponse.SC_NO_CONTENT;
2819:
2820:            /**
2821:             * Status code (301) indicating that the resource has permanently
2822:             * moved to a new location, and that future references should use a
2823:             * new URI with their requests.
2824:             */
2825:            public static final int SC_MOVED_PERMANENTLY = HttpServletResponse.SC_MOVED_PERMANENTLY;
2826:
2827:            /**
2828:             * Status code (302) indicating that the resource has temporarily
2829:             * moved to another location, but that future references should
2830:             * still use the original URI to access the resource.
2831:             */
2832:            public static final int SC_MOVED_TEMPORARILY = HttpServletResponse.SC_MOVED_TEMPORARILY;
2833:
2834:            /**
2835:             * Status code (304) indicating that a conditional GET operation
2836:             * found that the resource was available and not modified.
2837:             */
2838:            public static final int SC_NOT_MODIFIED = HttpServletResponse.SC_NOT_MODIFIED;
2839:
2840:            /**
2841:             * Status code (400) indicating the request sent by the client was
2842:             * syntactically incorrect.
2843:             */
2844:            public static final int SC_BAD_REQUEST = HttpServletResponse.SC_BAD_REQUEST;
2845:
2846:            /**
2847:             * Status code (401) indicating that the request requires HTTP
2848:             * authentication.
2849:             */
2850:            public static final int SC_UNAUTHORIZED = HttpServletResponse.SC_UNAUTHORIZED;
2851:
2852:            /**
2853:             * Status code (403) indicating the server understood the request
2854:             * but refused to fulfill it.
2855:             */
2856:            public static final int SC_FORBIDDEN = HttpServletResponse.SC_FORBIDDEN;
2857:
2858:            /**
2859:             * Status code (404) indicating that the requested resource is not
2860:             * available.
2861:             */
2862:            public static final int SC_NOT_FOUND = HttpServletResponse.SC_NOT_FOUND;
2863:
2864:            /**
2865:             * Status code (500) indicating an error inside the HTTP service
2866:             * which prevented it from fulfilling the request.
2867:             */
2868:            public static final int SC_INTERNAL_SERVER_ERROR = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
2869:
2870:            /**
2871:             * Status code (501) indicating the HTTP service does not support
2872:             * the functionality needed to fulfill the request.
2873:             */
2874:            public static final int SC_NOT_IMPLEMENTED = HttpServletResponse.SC_NOT_IMPLEMENTED;
2875:
2876:            /**
2877:             * Status code (502) indicating that the HTTP server received an
2878:             * invalid response from a server it consulted when acting as a
2879:             * proxy or gateway.
2880:             */
2881:            public static final int SC_BAD_GATEWAY = HttpServletResponse.SC_BAD_GATEWAY;
2882:
2883:            /**
2884:             * Status code (503) indicating that the HTTP service is
2885:             * temporarily overloaded, and unable to handle the request.
2886:             */
2887:            public static final int SC_SERVICE_UNAVAILABLE = HttpServletResponse.SC_SERVICE_UNAVAILABLE;
2888:
2889:            /**
2890:             * Status code (100) indicating the client may continue with
2891:             * its request.  This interim response is used to inform the
2892:             * client that the initial part of the request has been
2893:             * received and has not yet been rejected by the server.
2894:             */
2895:            public static final int SC_CONTINUE = 100;
2896:
2897:            /**
2898:             * Status code (405) indicating the method specified is not
2899:             * allowed for the resource.
2900:             */
2901:            public static final int SC_METHOD_NOT_ALLOWED = 405;
2902:
2903:            /**
2904:             * Status code (409) indicating that the request could not be
2905:             * completed due to a conflict with the current state of the
2906:             * resource.
2907:             */
2908:            public static final int SC_CONFLICT = 409;
2909:
2910:            /**
2911:             * Status code (412) indicating the precondition given in one
2912:             * or more of the request-header fields evaluated to false
2913:             * when it was tested on the server.
2914:             */
2915:            public static final int SC_PRECONDITION_FAILED = 412;
2916:
2917:            /**
2918:             * Status code (413) indicating the server is refusing to
2919:             * process a request because the request entity is larger
2920:             * than the server is willing or able to process.
2921:             */
2922:            public static final int SC_REQUEST_TOO_LONG = 413;
2923:
2924:            /**
2925:             * Status code (415) indicating the server is refusing to service
2926:             * the request because the entity of the request is in a format
2927:             * not supported by the requested resource for the requested
2928:             * method.
2929:             */
2930:            public static final int SC_UNSUPPORTED_MEDIA_TYPE = 415;
2931:
2932:            // -------------------------------------------- Extended WebDav status code
2933:
2934:            /**
2935:             * Status code (207) indicating that the response requires
2936:             * providing status for multiple independent operations.
2937:             */
2938:            public static final int SC_MULTI_STATUS = 207;
2939:            // This one colides with HTTP 1.1
2940:            // "207 Parital Update OK"
2941:
2942:            /**
2943:             * Status code (418) indicating the entity body submitted with
2944:             * the PATCH method was not understood by the resource.
2945:             */
2946:            public static final int SC_UNPROCESSABLE_ENTITY = 418;
2947:            // This one colides with HTTP 1.1
2948:            // "418 Reauthentication Required"
2949:
2950:            /**
2951:             * Status code (419) indicating that the resource does not have
2952:             * sufficient space to record the state of the resource after the
2953:             * execution of this method.
2954:             */
2955:            public static final int SC_INSUFFICIENT_SPACE_ON_RESOURCE = 419;
2956:            // This one colides with HTTP 1.1
2957:            // "419 Proxy Reauthentication Required"
2958:
2959:            /**
2960:             * Status code (420) indicating the method was not executed on
2961:             * a particular resource within its scope because some part of
2962:             * the method's execution failed causing the entire method to be
2963:             * aborted.
2964:             */
2965:            public static final int SC_METHOD_FAILURE = 420;
2966:
2967:            /**
2968:             * Status code (423) indicating the destination resource of a
2969:             * method is locked, and either the request did not contain a
2970:             * valid Lock-Info header, or the Lock-Info header identifies
2971:             * a lock held by another principal.
2972:             */
2973:            public static final int SC_LOCKED = 423;
2974:
2975:            // ------------------------------------------------------------ Initializer
2976:
2977:            static {
2978:                // HTTP 1.0 tatus Code
2979:                addStatusCodeMap(SC_OK, "OK");
2980:                addStatusCodeMap(SC_CREATED, "Created");
2981:                addStatusCodeMap(SC_ACCEPTED, "Accepted");
2982:                addStatusCodeMap(SC_NO_CONTENT, "No Content");
2983:                addStatusCodeMap(SC_MOVED_PERMANENTLY, "Moved Permanently");
2984:                addStatusCodeMap(SC_MOVED_TEMPORARILY, "Moved Temporarily");
2985:                addStatusCodeMap(SC_NOT_MODIFIED, "Not Modified");
2986:                addStatusCodeMap(SC_BAD_REQUEST, "Bad Request");
2987:                addStatusCodeMap(SC_UNAUTHORIZED, "Unauthorized");
2988:                addStatusCodeMap(SC_FORBIDDEN, "Forbidden");
2989:                addStatusCodeMap(SC_NOT_FOUND, "Not Found");
2990:                addStatusCodeMap(SC_INTERNAL_SERVER_ERROR,
2991:                        "Internal Server Error");
2992:                addStatusCodeMap(SC_NOT_IMPLEMENTED, "Not Implemented");
2993:                addStatusCodeMap(SC_BAD_GATEWAY, "Bad Gateway");
2994:                addStatusCodeMap(SC_SERVICE_UNAVAILABLE, "Service Unavailable");
2995:                addStatusCodeMap(SC_CONTINUE, "Continue");
2996:                addStatusCodeMap(SC_METHOD_NOT_ALLOWED, "Method Not Allowed");
2997:                addStatusCodeMap(SC_CONFLICT, "Conflict");
2998:                addStatusCodeMap(SC_PRECONDITION_FAILED, "Precondition Failed");
2999:                addStatusCodeMap(SC_REQUEST_TOO_LONG, "Request Too Long");
3000:                addStatusCodeMap(SC_UNSUPPORTED_MEDIA_TYPE,
3001:                        "Unsupported Media Type");
3002:                // WebDav Status Codes
3003:                addStatusCodeMap(SC_MULTI_STATUS, "Multi-Status");
3004:                addStatusCodeMap(SC_UNPROCESSABLE_ENTITY,
3005:                        "Unprocessable Entity");
3006:                addStatusCodeMap(SC_INSUFFICIENT_SPACE_ON_RESOURCE,
3007:                        "Insufficient Space On Resource");
3008:                addStatusCodeMap(SC_METHOD_FAILURE, "Method Failure");
3009:                addStatusCodeMap(SC_LOCKED, "Locked");
3010:            }
3011:
3012:            // --------------------------------------------------------- Public Methods
3013:
3014:            /**
3015:             * Returns the HTTP status text for the HTTP or WebDav status code
3016:             * specified by looking it up in the static mapping.  This is a
3017:             * static function.
3018:             *
3019:             * @param   nHttpStatusCode [IN] HTTP or WebDAV status code
3020:             * @return  A string with a short descriptive phrase for the
3021:             *                  HTTP status code (e.g., "OK").
3022:             */
3023:            public static String getStatusText(int nHttpStatusCode) {
3024:                Integer intKey = new Integer(nHttpStatusCode);
3025:
3026:                if (!mapStatusCodes.containsKey(intKey)) {
3027:                    return "";
3028:                } else {
3029:                    return (String) mapStatusCodes.get(intKey);
3030:                }
3031:            }
3032:
3033:            // -------------------------------------------------------- Private Methods
3034:
3035:            /**
3036:             * Adds a new status code -> status text mapping.  This is a static
3037:             * method because the mapping is a static variable.
3038:             *
3039:             * @param   nKey    [IN] HTTP or WebDAV status code
3040:             * @param   strVal  [IN] HTTP status text
3041:             */
3042:            private static void addStatusCodeMap(int nKey, String strVal) {
3043:                mapStatusCodes.put(new Integer(nKey), strVal);
3044:            }
3045:
3046:        };
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.