You are viewing a plain text version of this content. The canonical link for it is here.
Posted to slide-dev@jakarta.apache.org by re...@locus.apache.org on 2000/11/22 07:20:48 UTC

cvs commit: jakarta-slide/src/webdav/server/org/apache/slide/webdav/method CopyMethod.java DeleteMethod.java GetMethod.java HeadMethod.java LockMethod.java MkcolMethod.java MoveMethod.java OptionsMethod.java PostMethod.java PropFindMethod.java PropPatchMethod.java PutMethod.java UnlockMethod.java WebdavMethod.java

remm        00/11/21 22:20:47

  Added:       src/webdav/server/org/apache/slide/webdav
                        WebdavException.java WebdavServlet.java
               src/webdav/server/org/apache/slide/webdav/common
                        WebdavStatus.java WebdavXMLPrinter.java
               src/webdav/server/org/apache/slide/webdav/method
                        CopyMethod.java DeleteMethod.java GetMethod.java
                        HeadMethod.java LockMethod.java MkcolMethod.java
                        MoveMethod.java OptionsMethod.java PostMethod.java
                        PropFindMethod.java PropPatchMethod.java
                        PutMethod.java UnlockMethod.java WebdavMethod.java
  Log:
  - Move the DAV servlet to src/webdav/server.
  
  Revision  Changes    Path
  1.1                  jakarta-slide/src/webdav/server/org/apache/slide/webdav/WebdavException.java
  
  Index: WebdavException.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/WebdavException.java,v 1.1 2000/11/22 06:20:45 remm Exp $
   * $Revision: 1.1 $
   * $Date: 2000/11/22 06:20:45 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */ 
  
  package org.apache.slide.webdav;
  
  import java.io.Writer;
  import java.io.IOException;
  import javax.servlet.*;
  import javax.servlet.http.*;
  import org.apache.slide.common.SlideException;
  import org.apache.slide.webdav.common.WebdavStatus;
  
  /**
   * Webdav exception class.
   * 
   * @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
   */
  public class WebdavException extends SlideException {
      
      
      // ----------------------------------------------------- Instance Variables
      
      
      /**
       * HTTP status code associated with the exception.
       */
      protected int statusCode;
      
      
      // ----------------------------------------------------------- Constructors
      
      
      /**
       * Constructor.
       * 
       * @param statusCode Exception status code
       */
      public WebdavException(int statusCode) {
  	super(WebdavStatus.getStatusText(statusCode));
  	this.statusCode = statusCode;
      }
      
      
      // --------------------------------------------------------- Public Methods
      
      
      /**
       * Returns an HTTP formatted error page.
       * 
       * @param resp HTTP servlet response
       */
      public void writeErrorPage(HttpServletResponse resp) {
          try {
              Writer writer = resp.getWriter();
          } catch (IOException e) {
          }
      }
      
  }
  
  
  
  1.1                  jakarta-slide/src/webdav/server/org/apache/slide/webdav/WebdavServlet.java
  
  Index: WebdavServlet.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/WebdavServlet.java,v 1.1 2000/11/22 06:20:46 remm Exp $
   * $Revision: 1.1 $
   * $Date: 2000/11/22 06:20:46 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */ 
  
  package org.apache.slide.webdav;
  
  import java.io.*;
  import java.util.*;
  import java.security.Principal;
  import java.text.DateFormat;
  import java.text.SimpleDateFormat;
  import javax.servlet.*;
  import javax.servlet.http.*;
  import javax.xml.parsers.SAXParser;
  import javax.xml.parsers.SAXParserFactory;
  import org.xml.sax.*;
  import org.xml.sax.helpers.*;
  import org.apache.slide.webdav.method.*;
  import org.apache.slide.webdav.common.*;
  import org.apache.slide.structure.*;
  import org.apache.slide.common.*;
  import org.apache.slide.util.conf.*;
  import org.apache.slide.authenticate.SecurityToken;
  
  /**
   * WebDAV Servlet.
   * 
   * @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
   */
  public class WebdavServlet extends HttpServlet {
      
      
      // -------------------------------------------------------------- Constants
      
      
      /**
       * HTTP Date format pattern (RFC 2068, 822, 1123).
       */
      public static final String DATE_FORMAT = "EEE, d MMM yyyy kk:mm:ss z";
      
      
      /**
       * Date formatter.
       */
      private static final DateFormat formatter = 
          new SimpleDateFormat(DATE_FORMAT);
      
      
      // ----------------------------------------------------- Instance Variables
      
      
      /**
       * Access token to the namespace.
       */
      NamespaceAccessToken token;
      
      
      // -------------------------------------------------------- Private Methods
      
      
      /**
       * Show HTTP header information.
       */
      private void showRequestInfo(HttpServletRequest req) {
  	
  	System.out.println();
  	System.out.println("SlideDAV Request Info");
  	System.out.println();
  	
  	// Show generic info
  	System.out.println("Encoding : " + req.getCharacterEncoding());
  	System.out.println("Length : " + req.getContentLength());
  	System.out.println("Type : " + req.getContentType());
  	
  	System.out.println();
  	System.out.println("Parameters");
  	
  	Enumeration parameters = req.getParameterNames();
  	
  	while (parameters.hasMoreElements()) {
  	    String paramName = (String) parameters.nextElement();
  	    String[] values = req.getParameterValues(paramName);
  	    System.out.print(paramName + " : ");
  	    for (int i = 0; i < values.length; i++) {
  		System.out.print(values[i] + ", ");
  	    }
  	    System.out.println();
  	}
  	
  	System.out.println();
  	
  	System.out.println("Protocol : " + req.getProtocol());
  	System.out.println("Address : " + req.getRemoteAddr());
  	System.out.println("Host : " + req.getRemoteHost());
  	System.out.println("Scheme : " + req.getScheme());
  	System.out.println("Server Name : " + req.getServerName());
  	System.out.println("Server Port : " + req.getServerPort());
  	
  	System.out.println();
  	System.out.println("Attributes");
  	
  	Enumeration attributes = req.getAttributeNames();
  	
  	while (attributes.hasMoreElements()) {
  	    String attributeName = (String) attributes.nextElement();
  	    System.out.print(attributeName + " : ");
  	    System.out.println(req.getAttribute(attributeName).toString());
  	}
  	
  	System.out.println();
  	
  	// Show HTTP info
  	System.out.println();
  	System.out.println("HTTP Header Info");
  	System.out.println();
  	
  	System.out.println("Authentication Type : " + req.getAuthType());
  	System.out.println("HTTP Method : " + req.getMethod());
  	System.out.println("Path Info : " + req.getPathInfo());
  	System.out.println("Path translated : " + req.getPathTranslated());
  	System.out.println("Query string : " + req.getQueryString());
  	System.out.println("Remote user : " + req.getRemoteUser());
  	System.out.println("Requested session id : " 
                             + req.getRequestedSessionId());
  	System.out.println("Request URI : " + req.getRequestURI());
  	System.out.println("Context path : " + req.getContextPath());
          System.out.println("Servlet path : " + req.getServletPath());
          System.out.println("User principal : " + req.getUserPrincipal());
          
  	
  	System.out.println();
  	System.out.println("Headers : ");
  	
  	Enumeration headers = req.getHeaderNames();
  	
  	while (headers.hasMoreElements()) {
  	    String headerName = (String) headers.nextElement();
  	    System.out.print(headerName + " : ");
  	    System.out.println(req.getHeader(headerName));
  	}
  	
  	// Show session info
  	HttpSession session = req.getSession(false);
          
  	System.out.println();
  	System.out.println("End Request Info");
  	System.out.println();
  	System.out.println();
  	
      }
      
      
      /**
       * Create Slide Method form the HTTP Method.
       * 
       * @return WebdavMethod 
       * @exception WebdavException 
       */
      private WebdavMethod createWebdavMethod
  	(HttpServletRequest req, HttpServletResponse resp)
  	throws WebdavException {
          
  	String methodName = req.getMethod();
  	
  	WebdavMethod resultMethod = null;
  	
  	if (methodName.equalsIgnoreCase("GET")) {
  	    resultMethod = new GetMethod(this, token, req, resp);
  	} else if (methodName.equalsIgnoreCase("PROPFIND")) {
  	    resultMethod = new PropFindMethod(this, token, req, resp);
  	} else if (methodName.equalsIgnoreCase("HEAD")) {
  	    resultMethod = new HeadMethod(this, token, req, resp);
  	} else if (methodName.equalsIgnoreCase("LOCK")) {
  	    resultMethod = new LockMethod(this, token, req, resp);
  	} else if (methodName.equalsIgnoreCase("UNLOCK")) {
  	    resultMethod = new UnlockMethod(this, token, req, resp);
  	} else if (methodName.equalsIgnoreCase("OPTIONS")) {
  	    resultMethod = new OptionsMethod(this, token, req, resp);
  	} else if (methodName.equalsIgnoreCase("PUT")) {
  	    resultMethod = new PutMethod(this, token, req, resp);
  	} else if (methodName.equalsIgnoreCase("MKCOL")) {
  	    resultMethod = new MkcolMethod(this, token, req, resp);
  	} else if (methodName.equalsIgnoreCase("POST")) {
  	    resultMethod = new PostMethod(this, token, req, resp);
  	} else if (methodName.equalsIgnoreCase("COPY")) {
  	    resultMethod = new CopyMethod(this, token, req, resp);
  	} else if (methodName.equalsIgnoreCase("MOVE")) {
  	    resultMethod = new MoveMethod(this, token, req, resp);
  	} else if (methodName.equalsIgnoreCase("DELETE")) {
  	    resultMethod = new DeleteMethod(this, token, req, resp);
  	} else if (methodName.equalsIgnoreCase("PROPPATCH")) {
  	    resultMethod = new PropPatchMethod(this, token, req, resp);
  	}
  	
  	if (resultMethod == null) {
  	    throw new WebdavException(WebdavStatus.SC_BAD_REQUEST);
  	}
          
  	return resultMethod;
  	
      }
      
      
      // -------------------------------------------------------- Servlet Methods
      
      
      protected void service (HttpServletRequest req, HttpServletResponse resp)
          throws ServletException, IOException {
          
          //showRequestInfo(req);
          
          resp.setStatus(WebdavStatus.SC_OK);
          
          WebdavMethod method = null;
          
          try {
              //System.out.println(System.currentTimeMillis"Parsing request");
              method = createWebdavMethod(req, resp);
              method.run();
          } catch (WebdavException e) {
              // There has been an error somewhere ...
              // TODO : Show error page.
              System.out.println(e.getMessage());
          } catch (Throwable e) {
              // If something goes really wrong ...
              e.printStackTrace();
          }
          
      }
      
      
      /**
       * Manages some initialization stuff on the server.
       */
      public void init()
          throws ServletException {
          
          String namespaceName = "webdav";
          String domainConfigFile = "/Domain.xml";
          String managerServletPath = "/manager/";
          
          String value = null;
  	try {
  	    value = getServletConfig().getInitParameter("namespace");
              if (value != null)
                  namespaceName = value;
          } catch (Throwable t) {
  	    ;
  	}
  	try {
  	    value = getServletConfig().getInitParameter("domain");
              if (value != null)
                  domainConfigFile = value;
          } catch (Throwable t) {
  	    ;
  	}
  	try {
  	    value = getServletConfig().getInitParameter("manager");
              if (value != null)
                  managerServletPath = value;
          } catch (Throwable t) {
  	    ;
  	}
          
          WebdavMethod.init(managerServletPath);
          
          if (!Domain.isInitialized()) {
              
              try {
                  
                  SAXParserFactory factory = SAXParserFactory.newInstance();
                  factory.setNamespaceAware(false);
                  factory.setValidating(false);
                  SAXParser parser = factory.newSAXParser();
                  
                  InputStream is = 
                      getServletContext().getResourceAsStream(domainConfigFile);
                  if (is == null)
                      throw new ServletException("Can't find init file");
                  Populate pop = new Populate();
                  Configuration slideConfiguration = 
                      new ConfigurationElement(pop.load(new InputSource(is), 
                                                        parser.getParser()));
                  
                  Domain.init(slideConfiguration);
                  
              } catch (Throwable t) {
                  t.printStackTrace();
                  throw new ServletException(t.getMessage());
              }
              
          }
          
          token = Domain.accessNamespace(new SecurityToken(this), namespaceName);
          
      }
      
      
      /**
       * Destroy servlet.
       */
      public void destroy() {
          Domain.closeNamespace(token);
      }
      
  }
  
  
  
  1.1                  jakarta-slide/src/webdav/server/org/apache/slide/webdav/common/WebdavStatus.java
  
  Index: WebdavStatus.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/common/WebdavStatus.java,v 1.1 2000/11/22 06:20:46 remm Exp $
   * $Revision: 1.1 $
   * $Date: 2000/11/22 06:20:46 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */ 
  
  package org.apache.slide.webdav.common;
  
  import javax.servlet.http.HttpServletResponse;
  import javax.servlet.http.HttpServletRequest;
  import javax.servlet.ServletOutputStream;
  import java.io.IOException;
  import java.io.OutputStream;
  import java.util.Hashtable;
  import java.util.Enumeration;
  import java.util.NoSuchElementException;
  import org.apache.slide.common.*;
  
  /**
   * Extended HTTP protocols used by WebDAV.
   *
   * @author Marc Eaddy
   * @version $Revision: 1.1 $
   */
  public class WebdavStatus {
      
      /**
       * This Hashtable contains the mapping of HTTP and WebDAV
       * status codes to descriptive text.  This is a static
       * variable.
       */
      private static Hashtable mapStatusCodes = new Hashtable();
      
      /**
       * Adds a new status code -> status text mapping.  This is a static
       * method because the mapping is a static variable.
       * 
       * @param	nKey	[IN] HTTP or WebDAV status code
       * @param	strVal	[IN] HTTP status text
       */
      private static void addStatusCodeMap(int nKey, String strVal) {
  	mapStatusCodes.put(new Integer(nKey), strVal);
      }
      
      /**
       * Returns the HTTP status text for the HTTP or WebDav status code
       * specified by looking it up in the static mapping.  This is a
       * static function.
       * 
       * @param	nHttpStatusCode	[IN] HTTP or WebDAV status code
       * @return	A string with a short descriptive phrase for the
       *			HTTP status code (e.g., "OK").
       */
      public static String getStatusText(int nHttpStatusCode) {
  	Integer intKey = new Integer(nHttpStatusCode);
  	
  	if (!mapStatusCodes.containsKey(intKey)) {
  	    // DANGER!!! - RECURSIVE!!!
  	    return getStatusText(SC_INTERNAL_SERVER_ERROR);
  	} else {
  	    return (String) mapStatusCodes.get(intKey);
  	}
      }
      
      /*
       * HTTP 1.0 Server status codes; see RFC 1945.
       */
      
      /**
       * Status code (200) indicating the request succeeded normally.
       */
      public static final int SC_OK = HttpServletResponse.SC_OK;
      
      /**
       * Status code (201) indicating the request succeeded and created
       * a new resource on the server.
       */
      public static final int SC_CREATED = HttpServletResponse.SC_CREATED;
  
      /**
       * Status code (202) indicating that a request was accepted for
       * processing, but was not completed.
       */
      public static final int SC_ACCEPTED = HttpServletResponse.SC_ACCEPTED;
  
      /**
       * Status code (204) indicating that the request succeeded but that
       * there was no new information to return.
       */
      public static final int SC_NO_CONTENT = HttpServletResponse.SC_NO_CONTENT;
  
      /**
       * Status code (301) indicating that the resource has permanently
       * moved to a new location, and that future references should use a
       * new URI with their requests.
       */
      public static final int SC_MOVED_PERMANENTLY = HttpServletResponse.SC_MOVED_PERMANENTLY;
  
      /**
       * Status code (302) indicating that the resource has temporarily
       * moved to another location, but that future references should
       * still use the original URI to access the resource.
       */
      public static final int SC_MOVED_TEMPORARILY = HttpServletResponse.SC_MOVED_TEMPORARILY;
  
      /**
       * Status code (304) indicating that a conditional GET operation
       * found that the resource was available and not modified.
       */
      public static final int SC_NOT_MODIFIED = HttpServletResponse.SC_NOT_MODIFIED;
  
      /**
       * Status code (400) indicating the request sent by the client was
       * syntactically incorrect.
       */
      public static final int SC_BAD_REQUEST = HttpServletResponse.SC_BAD_REQUEST;
  
      /**
       * Status code (401) indicating that the request requires HTTP
       * authentication.
       */
      public static final int SC_UNAUTHORIZED = HttpServletResponse.SC_UNAUTHORIZED;
  
      /**
       * Status code (403) indicating the server understood the request
       * but refused to fulfill it.
       */
      public static final int SC_FORBIDDEN = HttpServletResponse.SC_FORBIDDEN;
  
      /**
       * Status code (404) indicating that the requested resource is not
       * available.
       */
      public static final int SC_NOT_FOUND = HttpServletResponse.SC_NOT_FOUND;
  
      /**
       * Status code (500) indicating an error inside the HTTP service
       * which prevented it from fulfilling the request.
       */
      public static final int SC_INTERNAL_SERVER_ERROR = HttpServletResponse.SC_INTERNAL_SERVER_ERROR;
  
      /**
       * Status code (501) indicating the HTTP service does not support
       * the functionality needed to fulfill the request.
       */
      public static final int SC_NOT_IMPLEMENTED = HttpServletResponse.SC_NOT_IMPLEMENTED;
  
      /**
       * Status code (502) indicating that the HTTP server received an
       * invalid response from a server it consulted when acting as a
       * proxy or gateway.
       */
      public static final int SC_BAD_GATEWAY = HttpServletResponse.SC_BAD_GATEWAY;
  
      /**
       * Status code (503) indicating that the HTTP service is
       * temporarily overloaded, and unable to handle the request.
       */
      public static final int SC_SERVICE_UNAVAILABLE = HttpServletResponse.SC_SERVICE_UNAVAILABLE;
  
      /*
       * HTTP 1.1 Server status codes; see RFC 2048.  When JWS supports HTTP 1.1 we
       * will use the appropriate HttpServletRespones status codes.
       */
      
      /**
       * Status code (100) indicating the client may continue with
       * its request.  This interim response is used to inform the 
       * client that the initial part of the request has been
       * received and has not yet been rejected by the server.
       */
      public static final int SC_CONTINUE = 100;
  
      /**
       * Status code (405) indicating the method specified is not
       * allowed for the resource.
       */
      public static final int SC_METHOD_NOT_ALLOWED = 405;
      
      /**
       * Status code (409) indicating that the request could not be
       * completed due to a conflict with the current state of the
       * resource.
       */
      public static final int SC_CONFLICT	= 409;
  
      /**
       * Status code (412) indicating the precondition given in one
       * or more of the request-header fields evaluated to false
       * when it was tested on the server.
       */
      public static final int SC_PRECONDITION_FAILED = 412;
  
      /**
       * Status code (413) indicating the server is refusing to
       * process a request because the request entity is larger
       * than the server is willing or able to process.
       */
      public static final int SC_REQUEST_TOO_LONG	= 413;
  
      /**
       * Status code (415) indicating the server is refusing to service
       * the request because the entity of the request is in a format
       * not supported by the requested resource for the requested
       * method.
       */
      public static final int SC_UNSUPPORTED_MEDIA_TYPE = 415;
      
      
      /*
       * Extended WebDAV HTTP status codes; see <draft-ietf-webdav-protocol-05>.
       */
      
      /**
       * Status code (207) indicating that the response requires
       * providing status for multiple independent operations.
       */
      public static final int SC_MULTI_STATUS = 207;
      // This one colides with HTTP 1.1
      // "207 Parital Update OK"
      
      /**
       * Status code (418) indicating the entity body submitted with
       * the PATCH method was not understood by the resource.
       */
      public static final int SC_UNPROCESSABLE_ENTITY = 418;
      // This one colides with HTTP 1.1
      // "418 Reauthentication Required"
      
      /**
       * Status code (419) indicating that the resource does not have
       * sufficient space to record the state of the resource after the
       * execution of this method.
       */
      public static final int SC_INSUFFICIENT_SPACE_ON_RESOURCE = 419;
      // This one colides with HTTP 1.1
      // "419 Proxy Reauthentication Required"
      
      /**
       * Status code (420) indicating the method was not executed on
       * a particular resource within its scope because some part of
       * the method's execution failed causing the entire method to be
       * aborted.
       */
      public static final int SC_METHOD_FAILURE = 420;
      
      /**
       * Status code (423) indicating the destination resource of a
       * method is locked, and either the request did not contain a
       * valid Lock-Info header, or the Lock-Info header identifies
       * a lock held by another principal.
       */
      public static final int SC_LOCKED = 423;
      
      static {
  	// HTTP 1.0 Server status codes -- see RFC 1945
  	addStatusCodeMap(SC_OK, "OK");
  	addStatusCodeMap(SC_CREATED, "Created");
  	addStatusCodeMap(SC_ACCEPTED, "Accepted");
  	addStatusCodeMap(SC_NO_CONTENT, "No Content");
  	addStatusCodeMap(SC_MOVED_PERMANENTLY, "Moved Permanently");
  	addStatusCodeMap(SC_MOVED_TEMPORARILY, "Moved Temporarily");
  	addStatusCodeMap(SC_NOT_MODIFIED, "Not Modified");
  	addStatusCodeMap(SC_BAD_REQUEST, "Bad Request");
  	addStatusCodeMap(SC_UNAUTHORIZED, "Unauthorized");
  	addStatusCodeMap(SC_FORBIDDEN, "Forbidden");
  	addStatusCodeMap(SC_NOT_FOUND, "Not Found");
  	addStatusCodeMap(SC_INTERNAL_SERVER_ERROR, "Internal Server Error");
  	addStatusCodeMap(SC_NOT_IMPLEMENTED, "Not Implemented");
  	addStatusCodeMap(SC_BAD_GATEWAY, "Bad Gateway");
  	addStatusCodeMap(SC_SERVICE_UNAVAILABLE, "Service Unavailable");
  	
  	// HTTP 1.1 Server status codes -- see RFC 2048
  	addStatusCodeMap(SC_CONTINUE, "Continue");
  	addStatusCodeMap(SC_METHOD_NOT_ALLOWED, "Method Not Allowed");
  	addStatusCodeMap(SC_CONFLICT, "Conflict");
  	addStatusCodeMap(SC_PRECONDITION_FAILED, "Precondition Failed");
  	addStatusCodeMap(SC_REQUEST_TOO_LONG, "Request Too Long");
  	addStatusCodeMap(SC_UNSUPPORTED_MEDIA_TYPE, "Unsupported Media Type");
  	
  	// WebDav Server-specific status codes
  	addStatusCodeMap(SC_MULTI_STATUS, "Multi-Status");
  	addStatusCodeMap(SC_UNPROCESSABLE_ENTITY, "Unprocessable Entity");
  	addStatusCodeMap(SC_INSUFFICIENT_SPACE_ON_RESOURCE, "Insufficient Space On Resource");
  	addStatusCodeMap(SC_METHOD_FAILURE, "Method Failure");
  	addStatusCodeMap(SC_LOCKED, "Locked");
      }
      
  };
  
  
  
  1.1                  jakarta-slide/src/webdav/server/org/apache/slide/webdav/common/WebdavXMLPrinter.java
  
  Index: WebdavXMLPrinter.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/common/WebdavXMLPrinter.java,v 1.1 2000/11/22 06:20:46 remm Exp $
   * $Revision: 1.1 $
   * $Date: 2000/11/22 06:20:46 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */ 
  
  package org.apache.slide.webdav.common;
  
  /**
   * WebdavXMLPrinter helper class.
   * 
   * @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
   */
  public class WebdavXMLPrinter {
      
      
      // -------------------------------------------------------------- Constants
      
      
      /**
       * Opening tag.
       */
      public static final int OPENING = 0;
      
      
      /**
       * Closing tag.
       */
      public static final int CLOSING = 1;
      
      
      /**
       * Element with no content.
       */
      public static final int NO_CONTENT = 2;
      
      
      // ----------------------------------------------------- Instance Variables
      
      
      /**
       * Buffer.
       */
      protected StringBuffer buffer;
      
      
      // ----------------------------------------------------------- Constructors
      
      
      /**
       * Constructor.
       */
      public WebdavXMLPrinter() {
          buffer = new StringBuffer();
      }
      
      
      // --------------------------------------------------------- Public Methods
      
      
      /**
       * Retrieve generated XML.
       * 
       * @return String containing the generated XML
       */
      public String toString() {
          return buffer.toString();
      }
      
      
      /**
       * Write property to the XML.
       * 
       * @param namespace Namespace
       * @param namespaceInfo Namespace info
       * @param name Property name
       * @param value Property value
       */
      public void writeProperty(String namespace, String namespaceInfo, 
                                String name, String value) {
          writeElement(namespace, namespaceInfo, name, OPENING);
          buffer.append(value);
          writeElement(namespace, namespaceInfo, name, CLOSING);
      }
      
      
      /**
       * Write property to the XML.
       * 
       * @param namespace Namespace
       * @param name Property name
       * @param value Property value
       */
      public void writeProperty(String namespace, String name, String value) {
          writeElement(namespace, name, OPENING);
          buffer.append(value);
          writeElement(namespace, name, CLOSING);
      }
      
      
      /**
       * Write property to the XML.
       * 
       * @param namespace Namespace
       * @param name Property name
       */
      public void writeProperty(String namespace, String name) {
          writeElement(namespace, name, NO_CONTENT);
      }
      
      
      /**
       * Write an element.
       * 
       * @param name Element name
       * @param namespace Namespace abbreviation
       * @param type Element type
       */
      public void writeElement(String namespace, String name, int type) {
          writeElement(namespace, null, name, type);
      }
      
      
      /**
       * Write an element.
       * 
       * @param namespace Namespace abbreviation
       * @param namespaceInfo Namespace info
       * @param name Element name
       * @param type Element type
       */
      public void writeElement(String namespace, String namespaceInfo, 
                               String name, int type) {
          if ((namespace != null) && (namespace.length() > 0)) {
              switch (type) {
              case OPENING:
                  if (namespaceInfo != null) {
                      buffer.append("<" + namespace + ":" + name + " xmlns:" 
                                    + namespace + "=\"" 
                                    + namespaceInfo + "\">");
                  } else {
                      buffer.append("<" + namespace + ":" + name + ">");
                  }
                  break;
              case CLOSING:
                  buffer.append("</" + namespace + ":" + name + ">\n");
                  break;
              case NO_CONTENT:
              default:
                  if (namespaceInfo != null) {
                      buffer.append("<" + namespace + ":" + name + " xmlns:" 
                                    + namespace + "=\"" 
                                    + namespaceInfo + "\"/>");
                  } else {
                      buffer.append("<" + namespace + ":" + name + "/>");
                  }
                  break;
              }
          } else {
              switch (type) {
              case OPENING:
                  buffer.append("<" + name + ">");
                  break;
              case CLOSING:
                  buffer.append("</" + name + ">\n");
                  break;
              case NO_CONTENT:
              default:
                  buffer.append("<" + name + "/>");
                  break;
              }
          }
      }
      
      
      /**
       * Write text.
       * 
       * @param text Text to append
       */
      public void writeText(String text) {
          buffer.append(text);
      }
      
      
      /**
       * Write XML Header.
       */
      public void writeXMLHeader() {
          buffer.append("<?xml version=\"1.0\" encoding=\"utf-8\" ?>\n");
      }
      
      
  }
  
  
  
  1.1                  jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/CopyMethod.java
  
  Index: CopyMethod.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/CopyMethod.java,v 1.1 2000/11/22 06:20:46 remm Exp $
   * $Revision: 1.1 $
   * $Date: 2000/11/22 06:20:46 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */ 
  
  package org.apache.slide.webdav.method;
  
  import java.security.Principal;
  import java.io.*;
  import java.util.*;
  import javax.servlet.*;
  import javax.servlet.http.*;
  import org.apache.slide.common.*;
  import org.apache.slide.webdav.common.*;
  import org.apache.slide.webdav.*;
  import org.apache.slide.macro.*;
  import org.apache.slide.lock.*;
  import org.apache.slide.content.*;
  import org.apache.slide.security.AccessDeniedException;
  import org.apache.slide.structure.*;
  
  /**
   * COPY Method.
   * 
   * @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
   */
  public class CopyMethod extends WebdavMethod {
      
      
      // ----------------------------------------------------- Instance Variables
      
      
      /**
       * Id of the resosurce or collection which is to be copied.
       */
      private String sourceUri;
      
      
      /**
       * Uri of the target.
       */
      private String destinationUri;
      
      
      /**
       * Overwrite.
       */
      private boolean overwrite;
      
      
      // ----------------------------------------------------------- Constructors
      
      
      /**
       * COPY method constructor.
       * 
       * @param token Namespace access token
       * @param requestUri Request URI
       * @param principal Principal object, given by the servlet container
       * @param req HTTP request
       * @param resp HTTP response
       */
      public CopyMethod(GenericServlet servlet, NamespaceAccessToken token, 
                        HttpServletRequest req, HttpServletResponse resp) {
  	super(servlet, token, req, resp);
      }
      
      
      // ------------------------------------------------------ Protected Methods
      
      
      /**
       * Parse request.
       *
       * @exception WebdavException Does not happen
       */
      protected void parseRequest() 
          throws WebdavException {
          
          sourceUri = requestUri;
          if (sourceUri == null) {
              sourceUri = "/";
          }
          
          destinationUri = req.getHeader("Destination");
          
          String HTTPHeader = "http://";
          if (destinationUri.startsWith(HTTPHeader)) {
              destinationUri = destinationUri.substring(HTTPHeader.length());
          }
          
          String hostName = req.getServerName();
          if ((hostName != null) && (destinationUri.startsWith(hostName))) {
              destinationUri = destinationUri.substring(hostName.length());
          }
          
          if (destinationUri.startsWith(":")) {
              int firstSeparator = destinationUri.indexOf("/");
              if (firstSeparator < 0) {
                  destinationUri = "/";
              } else {
                  destinationUri = destinationUri.substring(firstSeparator);
              }
          }
          
          String contextPath = req.getContextPath();
          if ((contextPath != null) && 
              (destinationUri.startsWith(contextPath))) {
              destinationUri = destinationUri.substring(contextPath.length());
          }
          
          String pathInfo = req.getPathInfo();
          if (pathInfo != null) {
              String servletPath = req.getServletPath();
              if ((servletPath != null) && 
                  (destinationUri.startsWith(servletPath))) {
                  destinationUri = destinationUri
                      .substring(servletPath.length());
              }
          }
          
          String overwriteHeader = req.getHeader("Overwrite");
          
          if (overwriteHeader != null) {
              if (overwriteHeader.equalsIgnoreCase("T")) {
                  overwrite = true;
              } else {
                  overwrite = false;
              }
          } else {
              overwrite = true;
          }
          
      }
      
      
      /**
       * Execute request.
       * 
       * @exception WebdavException Unrecoverable error occured while copying
       */
      protected void executeRequest() 
          throws WebdavException {
          
          MacroParameters macroParameters = null;
          String status = null;
          
          if (overwrite) {
              macroParameters = Macro.RECURSIVE_OVERWRITE_PARAMETERS;
          } else {
              macroParameters = Macro.DEFAULT_PARAMETERS;
          }
          
          try {
              macro.copy(credToken, sourceUri, destinationUri, macroParameters);
              if (overwrite) {
                  resp.setStatus(WebdavStatus.SC_NO_CONTENT);
              } else {
                  resp.setStatus(WebdavStatus.SC_CREATED);
              }
          } catch (CopyMacroException e) {
              String errorMessage = generateErrorMessage(e);
              // Write it on the servlet writer
              //status = new String("HTTP/1.1 " + WebdavStatus.SC_MULTI_STATUS 
              //+ " " + WebdavStatus.getStatusText
              //(WebdavStatus.SC_MULTI_STATUS));
              resp.setStatus(WebdavStatus.SC_MULTI_STATUS);
              try {
                  resp.getWriter().write(errorMessage);
              } catch(IOException ex) {
                  // Critical error ... Servlet container is dead or something
                  ex.printStackTrace();
                  throw new WebdavException
                      (WebdavStatus.SC_INTERNAL_SERVER_ERROR);
              }
          } catch(DeleteMacroException e) {
              resp.setStatus(WebdavStatus.SC_PRECONDITION_FAILED);
          }
          
      }
      
      
      /**
       * Generate an XML error message.
       * 
       * @param macroException Nested exception
       * @return String XML message
       */
      protected String generateErrorMessage(CopyMacroException macroException) {
          
          WebdavXMLPrinter errorMessage = new WebdavXMLPrinter();
          
          errorMessage.writeXMLHeader();
          errorMessage.writeElement("d", "DAV", "multistatus", 
                                    WebdavXMLPrinter.OPENING);
          
          Enumeration nestedExceptionsList = macroException
              .enumerateExceptions();
          
          while (nestedExceptionsList.hasMoreElements()) {
              
              errorMessage.writeElement("d", "DAV", "response", 
                                        WebdavXMLPrinter.OPENING);
              
              SlideException ex = (SlideException) nestedExceptionsList
                  .nextElement();
              
              String status = new String();
              
              try {
                  throw ex;
              } catch(ObjectNotFoundException e) {
                  generateStatusText(errorMessage, e.getObjectUri(), 
                                     WebdavStatus.SC_INTERNAL_SERVER_ERROR);
              } catch(AccessDeniedException e) {
                  generateStatusText(errorMessage, e.getObjectUri(), 
                                     WebdavStatus.SC_FORBIDDEN);
              } catch(ObjectAlreadyExistsException e) {
                  generateStatusText(errorMessage, e.getObjectUri(), 
                                     WebdavStatus.SC_INTERNAL_SERVER_ERROR);
              } catch(ServiceAccessException e) {
                  generateStatusText(errorMessage, e.getMessage(), 
                                     WebdavStatus.SC_BAD_GATEWAY);
              } catch(LinkedObjectNotFoundException e) {
                  generateStatusText(errorMessage, e.getTargetUri(), 
                                     WebdavStatus.SC_INTERNAL_SERVER_ERROR);
              } catch(RevisionNotFoundException e) {
                  generateStatusText(errorMessage, e.getObjectUri(), 
                                     WebdavStatus.SC_INTERNAL_SERVER_ERROR);
              } catch(ObjectLockedException e) {
                  generateStatusText(errorMessage, e.getObjectUri(), 
                                     WebdavStatus.SC_LOCKED);
              } catch(SlideException e) {
                  generateStatusText(errorMessage, e.getMessage(), 
                                     WebdavStatus.SC_INTERNAL_SERVER_ERROR);
              }
              
              errorMessage.writeElement("d", "DAV", "response", 
                                        WebdavXMLPrinter.CLOSING);
              
          }
          
          errorMessage.writeElement("d", "DAV", "multistatus", 
                                    WebdavXMLPrinter.CLOSING);
          
          return errorMessage.toString();
          
      }
      
      
      /**
       * Generate status text.
       * 
       * @param printer XML Printer
       * @param href Uri of the object
       * @param statusCode HTTP status code of the error
       */
      protected void generateStatusText(WebdavXMLPrinter printer, String href, 
                                        int statusCode) {
          printer.writeElement("d", "href", WebdavXMLPrinter.OPENING);        
          printer.writeText(href);
          printer.writeElement("d", "href", WebdavXMLPrinter.CLOSING);
          printer.writeElement("d", "status", WebdavXMLPrinter.OPENING);        
          printer.writeText("HTTP/1.1 " + statusCode + " " 
                            + WebdavStatus.getStatusText(statusCode));
          printer.writeElement("d", "status", WebdavXMLPrinter.CLOSING);
      }
      
  }
  
  
  
  1.1                  jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/DeleteMethod.java
  
  Index: DeleteMethod.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/DeleteMethod.java,v 1.1 2000/11/22 06:20:46 remm Exp $
   * $Revision: 1.1 $
   * $Date: 2000/11/22 06:20:46 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */ 
  
  package org.apache.slide.webdav.method;
  
  import java.security.Principal;
  import java.io.*;
  import java.util.*;
  import javax.servlet.*;
  import javax.servlet.http.*;
  import org.apache.slide.common.*;
  import org.apache.slide.webdav.common.*;
  import org.apache.slide.webdav.*;
  import org.apache.slide.macro.*;
  import org.apache.slide.lock.*;
  import org.apache.slide.content.*;
  import org.apache.slide.security.AccessDeniedException;
  import org.apache.slide.structure.*;
  
  /**
   * DELETE method.
   * 
   * @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
   */
  public class DeleteMethod extends WebdavMethod {
      
      
      // ----------------------------------------------------- Instance Variables
      
      
      /**
       * Id of the resosurce or collection which is to be deleted.
       */
      private String toDelete;
      
      
      // ----------------------------------------------------------- Constructors
      
      
      /**
       * DELETE method constructor.
       * 
       * @param token Namespace access token
       * @param req HTTP request
       * @param resp HTTP response
       */
      public DeleteMethod(GenericServlet servlet, NamespaceAccessToken token, 
                          HttpServletRequest req, HttpServletResponse resp) {
          super(servlet, token, req, resp);
      }
      
      
      // ------------------------------------------------------ Protected Methods
      
      
      /**
       * Parse request.
       * 
       * @exception WebdavException Does not happen
       */
      protected void parseRequest() 
          throws WebdavException {
          toDelete = requestUri;
          if (toDelete == null) {
              toDelete = "/";
          }
      }
      
      
      /**
       * Execute request.
       * 
       * @exception WebdavException Unrecoverable error while deleting
       */
      protected void executeRequest() 
  	throws WebdavException {
  	
  	try {
  	    macro.delete(credToken, toDelete);
              resp.setStatus(WebdavStatus.SC_NO_CONTENT);
          } catch (DeleteMacroException e) {
              String errorMessage = generateErrorMessage(e);
              // Write it on the servlet writer
              resp.setStatus(WebdavStatus.SC_MULTI_STATUS);
              try {
                  resp.getWriter().write(errorMessage);
              } catch(IOException ex) {
                  // Critical error ... Servlet container is dead or something
                  ex.printStackTrace();
                  throw new WebdavException
                      (WebdavStatus.SC_INTERNAL_SERVER_ERROR);
              }
          }
          
      }
      
      /**
       * Generate an XML error message.
       * 
       * @param macroException Nested exception
       * @return String XML message
       */
      protected String generateErrorMessage
          (DeleteMacroException macroException) {
          
          WebdavXMLPrinter errorMessage = new WebdavXMLPrinter();
          
          errorMessage.writeXMLHeader();
          errorMessage.writeElement("d", "DAV", "multistatus", 
                                    WebdavXMLPrinter.OPENING);
          
          Enumeration nestedExceptionsList = 
              macroException.enumerateExceptions();
          
          while (nestedExceptionsList.hasMoreElements()) {
              
              errorMessage.writeElement("d", "DAV", "response", 
                                        WebdavXMLPrinter.OPENING);
              
              SlideException ex = 
                  (SlideException) nestedExceptionsList.nextElement();
              
              String status = new String();
              
              try {
                  throw ex;
              } catch(ObjectNotFoundException e) {
                  generateStatusText(errorMessage, e.getObjectUri(), 
                                     WebdavStatus.SC_INTERNAL_SERVER_ERROR);
              } catch(AccessDeniedException e) {
                  generateStatusText(errorMessage, e.getObjectUri(), 
                                     WebdavStatus.SC_FORBIDDEN);
              } catch(ObjectAlreadyExistsException e) {
                  generateStatusText(errorMessage, e.getObjectUri(), 
                                     WebdavStatus.SC_INTERNAL_SERVER_ERROR);
              } catch(ServiceAccessException e) {
                  generateStatusText(errorMessage, e.getMessage(), 
                                     WebdavStatus.SC_BAD_GATEWAY);
              } catch(LinkedObjectNotFoundException e) {
                  generateStatusText(errorMessage, e.getTargetUri(), 
                                     WebdavStatus.SC_INTERNAL_SERVER_ERROR);
              } catch(RevisionNotFoundException e) {
                  generateStatusText(errorMessage, e.getObjectUri(), 
                                     WebdavStatus.SC_INTERNAL_SERVER_ERROR);
              } catch(ObjectLockedException e) {
                  generateStatusText(errorMessage, e.getObjectUri(), 
                                     WebdavStatus.SC_LOCKED);
              } catch(SlideException e) {
                  generateStatusText(errorMessage, e.getMessage(), 
                                     WebdavStatus.SC_INTERNAL_SERVER_ERROR);
              }
              
              errorMessage.writeElement("d", "DAV", "response", 
                                        WebdavXMLPrinter.CLOSING);
              
          }
          
          errorMessage.writeElement("d", "DAV", "multistatus", 
                                    WebdavXMLPrinter.CLOSING);
          
          return errorMessage.toString();
          
      }
      
      
      /**
       * Generate status text.
       * 
       * @param printer XML Printer
       * @param href Uri of the object
       * @param statusCode HTTP status code of the error
       */
      protected void generateStatusText(WebdavXMLPrinter printer, String href, 
                                        int statusCode) {
          printer.writeElement("d", "href", WebdavXMLPrinter.OPENING);        
          printer.writeText(href);
          printer.writeElement("d", "href", WebdavXMLPrinter.CLOSING);
          printer.writeElement("d", "status", WebdavXMLPrinter.OPENING);        
          printer.writeText("HTTP/1.1 " + statusCode + " " 
                            + WebdavStatus.getStatusText(statusCode));
          printer.writeElement("d", "status", WebdavXMLPrinter.CLOSING);
      }
      
  }
  
  
  
  1.1                  jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/GetMethod.java
  
  Index: GetMethod.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/GetMethod.java,v 1.1 2000/11/22 06:20:46 remm Exp $
   * $Revision: 1.1 $
   * $Date: 2000/11/22 06:20:46 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */ 
  
  package org.apache.slide.webdav.method;
  
  import java.security.Principal;
  import java.io.*;
  import java.util.*;
  import java.text.SimpleDateFormat;
  import java.text.ParseException;
  import javax.servlet.*;
  import javax.servlet.http.*;
  import org.apache.slide.common.*;
  import org.apache.slide.security.AccessDeniedException;
  import org.apache.slide.webdav.common.*;
  import org.apache.slide.webdav.*;
  import org.apache.slide.util.Messages;
  import org.apache.slide.content.*;
  import org.apache.slide.lock.*;
  import org.apache.slide.security.*;
  import org.apache.slide.structure.*;
  
  /**
   * GET method.
   * 
   * @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
   */
  public class GetMethod extends WebdavMethod {
      
      
      // -------------------------------------------------------------- Constants
      
      
      protected final int BUFFER_SIZE = 2048;
      
      
      /**
       * The set of SimpleDateFormat formats to use in getDateHeader().
       */
      protected static final SimpleDateFormat formats[] = {
          new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US),
          new SimpleDateFormat("EEEEEE, dd-MMM-yy HH:mm:ss zzz", Locale.US),
          new SimpleDateFormat("EEE MMMM d HH:mm:ss yyyy", Locale.US)
      };
      
      
      /**
       * MIME multipart separation string
       */
      protected static final String mimeSeparation = "SLIDE_MIME_BOUNDARY";
      
      
      /**
       * The input buffer size to use when serving resources.
       */
      protected int input = 2048;
      
      
      /**
       * The output buffer size to use when serving resources.
       */
      protected int output = 2048;
      
      
      /**
       * Print content.
       */
      protected boolean printContent = true;
      
      
      // ----------------------------------------------------- Instance Variables
      
      
      /**
       * Resource to be retrieved.
       */
      private String resourcePath;
      
      
      // ----------------------------------------------------------- Constructors
      
      
      /**
       * GET Method constructor.
       * 
       * @param token Namespace access token
       * @param req HTTP request
       * @param resp HTTP response
       */
      public GetMethod(GenericServlet servlet, NamespaceAccessToken token, 
                       HttpServletRequest req, HttpServletResponse resp) {
          super(servlet, token, req, resp);
      }
      
      
      // ------------------------------------------------------ Protected Methods
      
      
      /**
       * Parse XML request.
       */
      protected void parseRequest() 
          throws WebdavException {
          resourcePath = requestUri;
          if (resourcePath == null) {
              resourcePath = "/";
          }
      }
      
      
      /**
       * Execute request.
       * 
       * @exception WebdavException Can't access resource
       */
      protected void executeRequest() 
          throws WebdavException {
          
          try {
              
              // Then we must get object contents ...
              
              ObjectNode object = structure.retrieve(credToken, resourcePath);
              NodeRevisionDescriptors revisionDescriptors = 
                  content.retrieve(credToken, resourcePath);
              
              if (revisionDescriptors.hasRevisions()) {
                  
                  // Retrieve latest revision descriptor
                  NodeRevisionDescriptor revisionDescriptor = 
                      content.retrieve(credToken, revisionDescriptors);
                  
                  if (isCollection(revisionDescriptor)) {
                      
                      Writer writer = resp.getWriter();
                      resp.setContentType("text/html");
                      displayDirectoryBrowsing(object, writer);
                      writer.close();
                      
                  } else {
                      
                      ResourceInfo resourceInfo = 
                          new ResourceInfo(resourcePath, revisionDescriptor);
                      
                      // Checking If headers
                      if (!checkIfHeaders(req, resp, resourceInfo))
                          return;
                      
                      ServletOutputStream os = resp.getOutputStream();
                      NodeRevisionContent revisionContent = 
                          content.retrieve(credToken, revisionDescriptors, 
                                           revisionDescriptor);
                      InputStream is = null;
                      if (printContent) {
                          is = content.retrieve
                              (credToken, revisionDescriptors,
                               revisionDescriptor).streamContent();
                      }
                      
                      Vector ranges = parseRange(req, resp, resourceInfo);
                      
                      // ETag header
                      resp.setHeader("ETag", getETag(resourceInfo, true));
                      resp.addHeader
                          ("Last-Modified", 
                           revisionDescriptor.getCreationDate().toString());
                      
                      if ( ((ranges == null) || (ranges.isEmpty())) 
                           && (req.getHeader("Range") == null) ) {
                          
                          resp.setContentType
                              (revisionDescriptor.getContentType());
                          resp.setContentLength
                              ((int) revisionDescriptor.getContentLength());
                          
                          // Copy the input stream to our output stream 
                          // (if requested)
                          if (printContent) {
                              resp.setBufferSize(output);
                              copy(resourceInfo, is, os);
                          }
                          
                      } else {
                          
                          if ((ranges == null) || (ranges.isEmpty()))
                              return;
                          
                          // Partial content response.
                          
                          resp.setStatus(HttpServletResponse.SC_PARTIAL_CONTENT);
                          
                          if (ranges.size() == 1) {
                              
                              Range range = (Range) ranges.elementAt(0);
                              resp.addHeader("Content-Range", "bytes " 
                                             + range.start
                                             + "-" + range.end + "/" 
                                             + range.length);
                              resp.setContentType
                                  (revisionDescriptor.getContentType());
                              
                              if (printContent) {
                                  resp.setBufferSize(output);
                                  copy(resourceInfo, is, os, range);
                              }
                              
                          } else {
                              
                              resp.setContentType
                                  ("multipart/byteranges; boundary="
                                   + mimeSeparation);
                              
                              if (printContent) {
                                  resp.setBufferSize(output);
                                  copy(resourceInfo, is, os, 
                                       ranges.elements(), 
                                       revisionDescriptor.getContentType());
                              }
                              
                          }
                          
                      }
                      
                  }
                  
              } else {
                  
                  Writer writer = resp.getWriter();
                  resp.setContentType("text/html");
                  displayDirectoryBrowsing(object, writer);
                  writer.close();
                  
              }
              
          } catch (RevisionNotFoundException e) {
              // 404 - Not found
              System.out.println(e.getMessage());
              resp.setStatus(WebdavStatus.SC_NOT_FOUND);
  	} catch (RevisionContentNotFoundException e) {
              // 404 - Not found
              System.out.println(e.getMessage());
              resp.setStatus(WebdavStatus.SC_NOT_FOUND);
  	} catch (ObjectLockedException e) {
              // Locked
              System.out.println(e.getMessage());
              resp.setStatus(WebdavStatus.SC_LOCKED);
  	} catch (RevisionDescriptorNotFoundException e) {
              // 404 - Not found
              System.out.println(e.getMessage());
              resp.setStatus(WebdavStatus.SC_NOT_FOUND);
  	} catch (ObjectNotFoundException e) {
              // 404 - Not found
              System.out.println(e.getMessage());
              resp.setStatus(WebdavStatus.SC_NOT_FOUND);
  	} catch (LinkedObjectNotFoundException e) {
              // 404 - Not found
              System.out.println(e.getMessage());
              resp.setStatus(WebdavStatus.SC_NOT_FOUND);
  	} catch (AccessDeniedException e) {
              // 403 - Forbidden
              System.out.println(e.getMessage());
              resp.setStatus(WebdavStatus.SC_FORBIDDEN);
  	} catch (ServiceAccessException e) {
  	    // 500 - Internal server error
              System.out.println(e.getMessage());
              resp.setStatus(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
  	    throw new WebdavException(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
  	} catch (IOException e) {
              e.printStackTrace();
              // Unable to write to output stream.
  	    // 500 - Internal server error
              resp.setStatus(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
          } catch (RuntimeException e) {
              e.printStackTrace();
  	    // 500 - Internal server error
              resp.setStatus(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
  	}
          
      }
      
      
      /**
       * Display a directory browsing page.
       */
      protected void displayDirectoryBrowsing(ObjectNode object, 
                                              Writer servletWriter) 
          throws IOException {
          
          String contextPath = req.getContextPath();
          if (contextPath == null)
              contextPath = "";
          
          String name = object.getUri();
          
          // Number of characters to trim from the beginnings of filenames
          int trim = name.length();
          if (!name.endsWith("/"))
              trim += 1;
          if (name.equals("/"))
              trim = 1;
          
          PrintWriter writer = new PrintWriter(servletWriter);
          
          // Render the page header
          writer.print("<html>\r\n");
          writer.print("<head>\r\n");
          writer.print("<title>");
          writer.print
              (Messages.format
               ("org.apache.slide.webdav.GetMethod.directorylistingfor", name));
          writer.print("</title>\r\n</head>\r\n");
          writer.print("<body bgcolor=\"white\">\r\n");
          writer.print("<table width=\"90%\" cellspacing=\"0\"" +
                       " cellpadding=\"5\" align=\"center\">\r\n");
          
          // Render the in-page title
          writer.print("<tr><td colspan=\"3\"><font size=\"+2\">\r\n<strong>");
          writer.print
              (Messages.format
               ("org.apache.slide.webdav.GetMethod.directorylistingfor", name));
          writer.print("</strong>\r\n</font></td></tr>\r\n");
          
          // Render the link to our parent (if required)
          String parentDirectory = name;
          if (parentDirectory.endsWith("/")) {
              parentDirectory = 
                  parentDirectory.substring(0, parentDirectory.length() - 1);
          }
          int slash = parentDirectory.lastIndexOf("/");
          if (slash >= 0) {
              String parent = name.substring(0, slash);
              writer.print("<tr><td colspan=\"5\" bgcolor=\"#ffffff\">\r\n");
              writer.print("<a href=\"");
              writer.print(rewriteUrl(contextPath));
              if (parent.equals(""))
                  parent = "/";
              writer.print(parent);
              writer.print("\">");
              writer.print(Messages.format
                           ("org.apache.slide.webdav.GetMethod.parent", parent));
              writer.print("</a>\r\n");
              writer.print("</td></tr>\r\n");
          }
          
          Enumeration permissionsList = null;
          Enumeration locksList = null;
          
          try {
              
              permissionsList = 
                  security.enumeratePermissions(credToken, object.getUri());
              locksList = lock.enumerateLocks(credToken, object.getUri());
              
          } catch (SlideException e) {
              
              // Any security based exception will be trapped here
              
              // Any locking based exception will be trapped here
              
          }
          
          // Displaying ACL info
          displayPermissions(permissionsList, writer, false);
          
          // Displaying lock info
          displayLocks(locksList, writer, false);
          
          writer.print("<tr><td colspan=\"5\" bgcolor=\"#ffffff\">");
          writer.print("&nbsp;");
          writer.print("</td></tr>\r\n");
          
          // Render the column headings
          writer.print("<tr bgcolor=\"#cccccc\">\r\n");
          writer.print("<td align=\"left\" colspan=\"3\">");
          writer.print("<font size=\"+1\"><strong>");
          writer.print(Messages.message
                       ("org.apache.slide.webdav.GetMethod.filename"));
          writer.print("</strong></font></td>\r\n");
          writer.print("<td align=\"center\"><font size=\"+1\"><strong>");
          writer.print(Messages.message
                       ("org.apache.slide.webdav.GetMethod.size"));
          writer.print("</strong></font></td>\r\n");
          writer.print("<td align=\"right\"><font size=\"+1\"><strong>");
          writer.print(Messages.message
                       ("org.apache.slide.webdav.GetMethod.lastModified"));
          writer.print("</strong></font></td>\r\n");
          writer.print("</tr>\r\n");
          
          Enumeration resources = object.enumerateChildren();
          boolean shade = false;
          
          while (resources.hasMoreElements()) {
              
              String currentResource = (String) resources.nextElement();
              
              NodeRevisionDescriptor currentDescriptor = null;
              
              permissionsList = null;
              locksList = null;
              
              try {
                  
                  NodeRevisionDescriptors revisionDescriptors = 
                      content.retrieve(credToken, currentResource);
                  // Retrieve latest revision descriptor
                  currentDescriptor = 
                      content.retrieve(credToken, revisionDescriptors);
                  
              } catch (SlideException e) {
                  
                  // Silent exception : Objects without any revision are 
                  // considered collections, and do not have any attributes
                  
                  // Any security based exception will be trapped here
                  
                  // Any locking based exception will be trapped here
                  
              }
              
              try {
                  
                  permissionsList = 
                      security.enumeratePermissions(credToken, currentResource);
                  locksList = lock.enumerateLocks(credToken, currentResource);
                  
              } catch (SlideException e) {
                  
                  // Any security based exception will be trapped here
                  
                  // Any locking based exception will be trapped here
                  
              }
              
              String trimmed = currentResource.substring(trim);
              if (trimmed.equalsIgnoreCase("WEB-INF") ||
                  trimmed.equalsIgnoreCase("META-INF"))
                  continue;
              
              writer.print("<tr");
              if (shade) {
                  writer.print(" bgcolor=\"dddddd\"");
              } else {
                  writer.print(" bgcolor=\"eeeeee\"");
              }
              writer.print(">\r\n");
              shade = !shade;
              
              writer.print("<td align=\"left\" colspan=\"3\">&nbsp;&nbsp;\r\n");
              writer.print("<a href=\"");
              writer.print(rewriteUrl(contextPath));
              writer.print(rewriteUrl(currentResource));
              writer.print("\"><tt>");
              writer.print(trimmed);
              if (isCollection(currentDescriptor)) {
                  writer.print("/");
              }
              writer.print("</tt></a></td>\r\n");
              
              writer.print("<td align=\"right\"><tt>");
              if (isCollection(currentDescriptor))
                  writer.print("&nbsp;");
              else
                  writer.print(renderSize(currentDescriptor.getContentLength()));
              writer.print("</tt></td>\r\n");
              
              writer.print("<td align=\"right\"><tt>");
              if (currentDescriptor != null) {
                  writer.print(currentDescriptor.getLastModified());
              } else {
                  writer.print("&nbsp;");
              }
              writer.print("</tt></td>\r\n");
              
              writer.print("</tr>\r\n");
              
              // Displaying ACL info
              displayPermissions(permissionsList, writer, shade);
              
              // Displaying lock info
              displayLocks(locksList, writer, shade);
              
          }
          
          // Render the page footer
          writer.print("<tr><td colspan=\"5\">&nbsp;</td></tr>\r\n");
          writer.print("<tr><td colspan=\"3\" bgcolor=\"#cccccc\">");
          writer.print("<font size=\"-1\">");
          writer.print(Messages.message
                       ("org.apache.slide.webdav.GetMethod.version"));
          writer.print("</font></td>\r\n");
          writer.print("<td colspan=\"2\" align=\"right\" bgcolor=\"#cccccc\">");
          writer.print("<font size=\"-1\">");
          writer.print(formats[0].format(new Date()));
          writer.print("</font></td></tr>\r\n");
          writer.print("</table>\r\n");
          writer.print("</body>\r\n");
          writer.print("</html>\r\n");
          
          // Return an input stream to the underlying bytes
          writer.flush();
          
      }
      
      
      /**
       * Display an ACL list.
       * 
       * @param permissionsList List of NodePermission objects
       * @param boolean Shade
       * @param writer The output will be appended to this writer
       */
      private void displayPermissions(Enumeration permissionsList,
                                      PrintWriter writer,
                                      boolean shade)
          throws IOException {
          
          if ((permissionsList != null) && (permissionsList.hasMoreElements())) {
              
              writer.print("<tr");
              if (!shade) {
                  writer.print(" bgcolor=\"dddddd\"");
              } else {
                  writer.print(" bgcolor=\"eeeeee\"");
              }
              writer.print(">\r\n");
              writer.print("<td align=\"left\" colspan=\"5\"><tt><b>");
              writer.print(Messages.message
                           ("org.apache.slide.webdav.GetMethod.aclinfo"));
              writer.print("</b></tt></td>\r\n");
              writer.print("</tr>\r\n");
              
              writer.print("<tr");
              if (!shade) {
                  writer.print(" bgcolor=\"dddddd\"");
              } else {
                  writer.print(" bgcolor=\"eeeeee\"");
              }
              writer.print(">\r\n");
              
              writer.print("<td align=\"left\"><tt><b>");
              writer.print(Messages.message
                           ("org.apache.slide.webdav.GetMethod.subject"));
              writer.print("</b></tt></td>\r\n");
              
              writer.print("<td align=\"left\"><tt><b>");
              writer.print(Messages.message
                           ("org.apache.slide.webdav.GetMethod.action"));
              writer.print("</b></tt></td>\r\n");
              
              writer.print("<td align=\"right\"><tt><b>");
              writer.print(Messages.message
                           ("org.apache.slide.webdav.GetMethod.inheritable"));
              writer.print("</b></tt></td>\r\n");
              
              writer.print("<td align=\"right\"><tt><b>");
              writer.print(Messages.message
                           ("org.apache.slide.webdav.GetMethod.deny"));
              writer.print("</b></tt></td>\r\n");
              
              writer.print("<td align=\"right\"><tt><b>");
              writer.print("<a href=\"");
              if (req.getContextPath() != null) {
                  writer.print(req.getContextPath());
              }
              writer.print(managerServletPath + token.getName() 
                           + "?command=addacl\">");
              writer.print(Messages.message
                           ("org.apache.slide.webdav.GetMethod.add"));
              writer.print("</a>");
              writer.print("</b></tt></td>\r\n");
              
              writer.print("</tr>\r\n");
              
              while (permissionsList.hasMoreElements()) {
                  
                  writer.print("<tr");
                  if (!shade) {
                      writer.print(" bgcolor=\"dddddd\"");
                  } else {
                      writer.print(" bgcolor=\"eeeeee\"");
                  }
                  writer.print(">\r\n");
                  
                  NodePermission currentPermission =
                      (NodePermission) permissionsList.nextElement();
                  
                  writer.print("<td align=\"left\"><tt>");
                  writer.print(currentPermission.getSubjectUri());
                  writer.print("</tt></td>\r\n");
                  
                  writer.print("<td align=\"left\"><tt>");
                  writer.print(currentPermission.getActionUri());
                  writer.print("</tt></td>\r\n");
                  
                  writer.print("<td align=\"right\"><tt>");
                  writer.print(currentPermission.isInheritable());
                  writer.print("</tt></td>\r\n");
                  
                  writer.print("<td align=\"right\"><tt>");
                  writer.print(currentPermission.isNegative());
                  writer.print("</tt></td>\r\n");
                  
                  writer.print("<td align=\"right\"><tt><b>");
                  writer.print("<a href=\"");
                  if (req.getContextPath() != null) {
                      writer.print(req.getContextPath());
                  }
                  writer.print(managerServletPath + token.getName() 
                               + "?command=removeacl"
                               + "&object=" + currentPermission.getObjectUri()
                               + "&subject=" + currentPermission.getSubjectUri()
                               + "&action=" + currentPermission.getActionUri()
                               + "\">");
                  writer.print(Messages.message
                               ("org.apache.slide.webdav.GetMethod.remove"));
                  writer.print("</a>");
                  writer.print("</b></tt></td>\r\n");
                  
                  writer.print("</tr>\r\n");
                      
              }
              
          }
          
      }
      
      
      /**
       * Display a lock list.
       * 
       * @param locksList List of NodeLock objects
       * @param boolean Shade
       * @param writer The output will be appended to this writer
       */
      private void displayLocks(Enumeration locksList, PrintWriter writer,
                                boolean shade)
          throws IOException {
          
          if ((locksList != null) && (locksList.hasMoreElements())) {
              
              writer.print("<tr");
              if (!shade) {
                  writer.print(" bgcolor=\"dddddd\"");
              } else {
                  writer.print(" bgcolor=\"eeeeee\"");
              }
              writer.print(">\r\n");
              writer.print("<td align=\"left\" colspan=\"5\"><tt><b>");
              writer.print(Messages.message
                           ("org.apache.slide.webdav.GetMethod.locksinfo"));
              writer.print("</b></tt></td>\r\n");
              writer.print("</tr>\r\n");
              
              writer.print("<tr");
              if (!shade) {
                  writer.print(" bgcolor=\"dddddd\"");
              } else {
                  writer.print(" bgcolor=\"eeeeee\"");
              }
              writer.print(">\r\n");
              
              writer.print("<td align=\"left\"><tt><b>");
              writer.print(Messages.message
                           ("org.apache.slide.webdav.GetMethod.subject"));
              writer.print("</b></tt></td>\r\n");
              
              writer.print("<td align=\"left\"><tt><b>");
              writer.print(Messages.message
                           ("org.apache.slide.webdav.GetMethod.type"));
              writer.print("</b></tt></td>\r\n");
              
              writer.print("<td align=\"right\"><tt><b>");
              writer.print(Messages.message
                           ("org.apache.slide.webdav.GetMethod.expiration"));
              writer.print("</b></tt></td>\r\n");
              
              writer.print("<td align=\"right\"><tt><b>");
              writer.print(Messages.message
                           ("org.apache.slide.webdav.GetMethod.inheritable"));
              writer.print("</b></tt></td>\r\n");
              
              writer.print("<td align=\"right\"><tt><b>");
              writer.print(Messages.message
                           ("org.apache.slide.webdav.GetMethod.exclusive"));
              writer.print("</b></tt></td>\r\n");
              
              writer.print("</tr>\r\n");
              
              while (locksList.hasMoreElements()) {
                  
                  writer.print("<tr");
                  if (!shade) {
                      writer.print(" bgcolor=\"dddddd\"");
                  } else {
                      writer.print(" bgcolor=\"eeeeee\"");
                  }
                  writer.print(">\r\n");
                  
                  NodeLock currentLock = (NodeLock) locksList.nextElement();
                  
                  writer.print("<td align=\"left\"><tt>");
                  writer.print(currentLock.getSubjectUri());
                  writer.print("</tt></td>\r\n");
                  
                  writer.print("<td align=\"left\"><tt>");
                  writer.print(currentLock.getTypeUri());
                  writer.print("</tt></td>\r\n");
                  
                  writer.print("<td align=\"right\"><tt>");
                  writer.print
                      (formats[0].format(currentLock.getExpirationDate()));
                  writer.print("</tt></td>\r\n");
                  
                  writer.print("<td align=\"right\"><tt>");
                  writer.print(currentLock.isInheritable());
                  writer.print("</tt></td>\r\n");
                  
                  writer.print("<td align=\"right\"><tt>");
                  writer.print(currentLock.isExclusive());
                  writer.print("</tt></td>\r\n");
                  
              }
              
          }
          
      }
      
      
      // -------------------------------------------------------- Private Methods
      
      
      /**
       * Render the specified file size (in bytes).
       *
       * @param size File size (in bytes)
       */
      private String renderSize(long size) {
          
          long leftSide = size / 1024;
          long rightSide = (size % 1024) / 103;	// Makes 1 digit
          if ((leftSide == 0) && (rightSide == 0) && (size > 0))
              rightSide = 1;
          
          return ("" + leftSide + "." + rightSide + " kb");
          
      }
      
      
      /**
       * URL rewriter.
       * 
       * @param path Path which has to be rewiten
       */
      private String rewriteUrl(String path) {
          
          String normalized = path;
          
          // Replace " " with "%20"
          while (true) {
              int index = normalized.indexOf(" ");
              if (index < 0)
                  break;
              normalized = normalized.substring(0, index) + "%20"
                  + normalized.substring(index + 1);
          }
          
          return normalized;
          
      }
      
      
      /**
       * Check if the conditions specified in the optional If headers are 
       * satisfied.
       * 
       * @param request The servlet request we are processing
       * @param response The servlet response we are creating
       * @param resourceInfo File object
       * @return boolean true if the resource meets all the specified conditions,
       * and false if any of the conditions is not satisfied, in which case
       * request processing is stopped
       */
      private boolean checkIfHeaders(HttpServletRequest request,
                                       HttpServletResponse response, 
                                       ResourceInfo resourceInfo)
          throws IOException {
          
          String eTag = getETag(resourceInfo, true);
          long fileLength = resourceInfo.length;
          long lastModified = resourceInfo.date;
          
          StringTokenizer commaTokenizer;
          
          String headerValue;
          
          // Checking If-Match
          headerValue = request.getHeader("If-Match");
          if (headerValue != null) {
              if (headerValue.indexOf("*") == -1) {
                  
                  commaTokenizer = new StringTokenizer(headerValue, ",");
                  boolean conditionSatisfied = false;
                  
                  while (!conditionSatisfied && commaTokenizer.hasMoreTokens()) {
                      String currentToken = commaTokenizer.nextToken();
                      if (currentToken.trim().equals(eTag))
                          conditionSatisfied = true;
                  }
                  
                  // If none of the given ETags match, 412 Precodition failed is
                  // sent back
                  if (!conditionSatisfied) {
                      response.sendError
                          (HttpServletResponse.SC_PRECONDITION_FAILED);
                      return false;
                  }
                  
              }
          }
          
          // Checking If-Modified-Since
          headerValue = request.getHeader("If-Modified-Since");
          if (headerValue != null) {
              
              // If an If-None-Match header has been specified, if modified since
              // is ignored.
              if (request.getHeader("If-None-Match") == null) {
                  
                  Date date = null;
                  
                  // Parsing the HTTP Date
                  for (int i = 0; (date == null) && (i < formats.length); i++) {
                      try {
                          date = formats[i].parse(headerValue);
                      } catch (ParseException e) {
                          ;
                      }
                  }
                  
                  if ((date != null) 
                      && (lastModified <= (date.getTime() + 1000)) ) {
                      // The entity has not been modified since the date 
                      // specified by the client. This is not an error case.
                      response.sendError
                          (HttpServletResponse.SC_NOT_MODIFIED);
                      return false;
                  }
                  
              }
              
          }
          
          // Checking If-None-Match
          headerValue = request.getHeader("If-None-Match");
          if (headerValue != null) {
              if (headerValue.indexOf("*") == -1) {
                  
                  commaTokenizer = new StringTokenizer(headerValue, ",");
                  boolean conditionSatisfied = false;
                  
                  while (!conditionSatisfied && commaTokenizer.hasMoreTokens()) {
                      String currentToken = commaTokenizer.nextToken();
                      if (currentToken.trim().equals(eTag))
                          conditionSatisfied = true;
                  }
                  
                  if (conditionSatisfied) {
                      
                      // For GET and HEAD, we should respond with 
                      // 304 Not Modified.
                      // For every other method, 412 Precondition Failed is sent
                      // back.
                      if ( ("GET".equals(request.getMethod()))
                           || ("HEAD".equals(request.getMethod())) ) {
                          response.sendError
                              (HttpServletResponse.SC_NOT_MODIFIED);
                          return false;
                      } else {
                          response.sendError
                              (HttpServletResponse.SC_PRECONDITION_FAILED);
                          return false;
                      }
                  }
                  
              } else {
                  if (resourceInfo.exists()) {
                      
                  }
              }
          }
          
          // Checking If-Unmodified-Since
          headerValue = request.getHeader("If-Unmodified-Since");
          if (headerValue != null) {
              
              Date date = null;
              
              // Parsing the HTTP Date
              for (int i = 0; (date == null) && (i < formats.length); i++) {
                  try {
                      date = formats[i].parse(headerValue);
                  } catch (ParseException e) {
                      ;
                  }
              }
              
              if ( (date != null) && (lastModified > date.getTime()) ) {
                  // The entity has not been modified since the date 
                  // specified by the client. This is not an error case.
                  response.sendError
                      (HttpServletResponse.SC_PRECONDITION_FAILED);
                  return false;
              }
              
          }
          
          return true;
      }
  
  
      /**
       * Get the ETag value associated with a file.
       * 
       * @param resourceInfo File object
       * @param strong True if we want a strong ETag, in which case a checksum
       * of the file has to be calculated
       */
      private String getETagValue(ResourceInfo resourceInfo, boolean strong) {
          // FIXME : Compute a strong ETag if requested, using an MD5 digest
          // of the file contents
          return resourceInfo.length + "-" + resourceInfo.date;
      }
  
  
      /**
       * Get the ETag associated with a file.
       * 
       * @param resourceInfo File object
       * @param strong True if we want a strong ETag, in which case a checksum
       * of the file has to be calculated
       */
      private String getETag(ResourceInfo resourceInfo, boolean strong) {
          if (strong)
              return "\"" + getETagValue(resourceInfo, strong) + "\"";
          else
              return "W/\"" + getETagValue(resourceInfo, strong) + "\"";
      }
  
  
      /**
       * Copy the contents of the specified input stream to the specified
       * output stream, and ensure that both streams are closed before returning
       * (even in the face of an exception).
       *
       * @param istream The input stream to read from
       * @param ostream The output stream to write to
       *
       * @exception IOException if an input/output error occurs
       */
      private void copy(ResourceInfo resourceInfo, 
                        InputStream resourceInputStream, 
                        ServletOutputStream ostream)
  	throws IOException {
  
          IOException exception = null;
              
          InputStream istream = new BufferedInputStream
              (resourceInputStream, input);
          
          // Copy the input stream to the output stream
          exception = copyRange(istream, ostream);
          
          // Clean up the input and output streams
          try {
              istream.close();
          } catch (Throwable t) {
              ;
          }
          
  	try {
  	    ostream.flush();
  	} catch (Throwable t) {
  	    ;
  	}
  	try {
  	    ostream.close();
  	} catch (Throwable t) {
  	    ;
  	}
  
  	// Rethrow any exception that has occurred
  	if (exception != null)
  	    throw exception;
  
      }
  
  
      /**
       * Copy the contents of the specified input stream to the specified
       * output stream, and ensure that both streams are closed before returning
       * (even in the face of an exception).
       *
       * @param resourceInfo The ResourceInfo object
       * @param ostream The output stream to write to
       * @param range Range the client wanted to retrieve
       * @exception IOException if an input/output error occurs
       */
      private void copy(ResourceInfo resourceInfo, 
                        InputStream resourceInputStream, 
                        ServletOutputStream ostream, 
                        Range range)
  	throws IOException {
          
          IOException exception = null;
          
          InputStream istream =
              new BufferedInputStream(resourceInputStream, input);
          exception = copyRange(istream, ostream, range.start, range.end);
          
  	// Clean up the input and output streams
  	try {
  	    istream.close();
  	} catch (Throwable t) {
  	    ;
  	}
  	try {
  	    ostream.flush();
  	} catch (Throwable t) {
  	    ;
  	}
  	try {
  	    ostream.close();
  	} catch (Throwable t) {
  	    ;
  	}
  
  	// Rethrow any exception that has occurred
  	if (exception != null)
  	    throw exception;
          
      }
  
  
      /**
       * Copy the contents of the specified input stream to the specified
       * output stream, and ensure that both streams are closed before returning
       * (even in the face of an exception).
       *
       * @param resourceInfo The ResourceInfo object
       * @param ostream The output stream to write to
       * @param ranges Enumeration of the ranges the client wanted to retrieve
       * @param contentType Content type of the resource
       * @exception IOException if an input/output error occurs
       */
      private void copy(ResourceInfo resourceInfo, 
                        InputStream resourceInputStream, 
                        ServletOutputStream ostream,
                        Enumeration ranges, String contentType)
  	throws IOException {
          
          IOException exception = null;
          
          while ( (exception == null) && (ranges.hasMoreElements()) ) {
              
              InputStream istream = 
                  new BufferedInputStream(resourceInputStream, input);
          
              Range currentRange = (Range) ranges.nextElement();
              
              // Writing MIME header.
              ostream.println("--" + mimeSeparation);
              if (contentType != null)
                  ostream.println("Content-Type: " + contentType);
              ostream.println("Content-Range: bytes " + currentRange.start
                             + "-" + currentRange.end + "/" 
                             + currentRange.length);
              ostream.println();
              
              // Printing content
              exception = copyRange(istream, ostream, currentRange.start,
                                    currentRange.end);
              
              try {
                  istream.close();
              } catch (Throwable t) {
                  ;
              }
              
          }
          
          ostream.print("--" + mimeSeparation + "--");
          
  	// Clean up the output streams
  	try {
  	    ostream.flush();
  	} catch (Throwable t) {
  	    ;
  	}
  	try {
  	    ostream.close();
  	} catch (Throwable t) {
  	    ;
  	}
  
  	// Rethrow any exception that has occurred
  	if (exception != null)
  	    throw exception;
          
      }
  
  
      /**
       * Copy the contents of the specified input stream to the specified
       * output stream, and ensure that both streams are closed before returning
       * (even in the face of an exception).
       *
       * @param istream The input stream to read from
       * @param ostream The output stream to write to
       * @return Exception which occured during processing
       */
      private IOException copyRange(InputStream istream, 
                                    ServletOutputStream ostream) {
          
  	// Copy the input stream to the output stream
  	IOException exception = null;
  	byte buffer[] = new byte[input];
  	int len = buffer.length;
  	while (true) {
  	    try {
                  len = istream.read(buffer);
                  if (len == -1)
                      break;
                  ostream.write(buffer, 0, len);
  	    } catch (IOException e) {
  		exception = e;
  		len = -1;
                  break;
  	    }
  	}
          return exception;
          
      }
  
  
      /**
       * Copy the contents of the specified input stream to the specified
       * output stream, and ensure that both streams are closed before returning
       * (even in the face of an exception).
       *
       * @param istream The input stream to read from
       * @param ostream The output stream to write to
       * @param start Start of the range which will be copied
       * @param end End of the range which will be copied
       * @return Exception which occured during processing
       */
      private IOException copyRange(InputStream istream, 
                                    ServletOutputStream ostream,
                                    long start, long end) {
          
          try {
              istream.skip(start);
          } catch (IOException e) {
              return e;
          }
          
  	IOException exception = null;
          long bytesToRead = end - start + 1;
          
  	byte buffer[] = new byte[input];
  	int len = buffer.length;
  	while ( (bytesToRead > 0) && (len >= buffer.length)) {
  	    try {
                  len = istream.read(buffer);
                  if (bytesToRead >= len) {
                      ostream.write(buffer, 0, len);
                      bytesToRead -= len; 
                  } else {
                      ostream.write(buffer, 0, (int) bytesToRead);
                      bytesToRead = 0;
                  }
  	    } catch (IOException e) {
  		exception = e;
  		len = -1;
  	    }
  	    if (len < buffer.length)
  		break;
  	}
          
          return exception;
          
      }
  
  
      /**
       * Parse the range header.
       * 
       * @param request The servlet request we are processing
       * @param response The servlet response we are creating
       * @return Vector of ranges
       */
      private Vector parseRange(HttpServletRequest request, 
                                HttpServletResponse response, 
                                ResourceInfo resourceInfo) 
          throws IOException {
          
          // Checking If-Range
          String headerValue = request.getHeader("If-Range");
          if (headerValue != null) {
              
              String eTag = getETag(resourceInfo, true);
              long lastModified = resourceInfo.date;
              
              Date date = null;
              
              // Parsing the HTTP Date
              for (int i = 0; (date == null) && (i < formats.length); i++) {
                  try {
                      date = formats[i].parse(headerValue);
                  } catch (ParseException e) {
                      ;
                  }
              }
              
              if (date == null) {
                  
                  // If the ETag the client gave does not match the entity
                  // etag, then the entire entity is returned.
                  if (!eTag.equals(headerValue.trim()))
                      return null;
                  
              } else {
                  
                  // If the timestamp of the entity the client got is older than
                  // the last modification date of the entity, the entire entity
                  // is returned.
                  if (lastModified > (date.getTime() + 1000))
                      return null;
                  
              }
              
          }
          
          long fileLength = resourceInfo.length;
          
          if (fileLength == 0)
              return null;
          
          // Retrieving the range header (if any is specified
          String rangeHeader = request.getHeader("Range");
          
          if (rangeHeader == null)
              return null;
          // bytes is the only range unit supported (and I don't see the point
          // of adding new ones).
          if (!rangeHeader.startsWith("bytes")) {
              response.sendError
                  (HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
              return null;
          }
          
          rangeHeader = rangeHeader.substring(6);
          
          // Vector which will contain all the ranges which are successfully
          // parsed.
          Vector result = new Vector();
          StringTokenizer commaTokenizer = new StringTokenizer(rangeHeader, ",");
          
          // Parsing the range list
          while (commaTokenizer.hasMoreTokens()) {
              String rangeDefinition = commaTokenizer.nextToken();
              
              Range currentRange = new Range();
              currentRange.length = fileLength;
              
              int dashPos = rangeDefinition.indexOf('-');
              
              if (dashPos == -1) {
                  response.sendError
                      (HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
                  return null;
              }
              
              if (dashPos == 0) {
                  
                  try {
                      long offset = Long.parseLong(rangeDefinition);
                      currentRange.start = fileLength + offset;
                      currentRange.end = fileLength - 1;
                  } catch (NumberFormatException e) {
                      response.sendError
                          (HttpServletResponse
                           .SC_REQUESTED_RANGE_NOT_SATISFIABLE);
                      return null;
                  }
                  
              } else {
                  
                  try {
                      currentRange.start = Long.parseLong
                          (rangeDefinition.substring(0, dashPos));
                      if (dashPos < rangeDefinition.length() - 1)
                          currentRange.end = Long.parseLong
                              (rangeDefinition.substring
                               (dashPos + 1, rangeDefinition.length()));
                      else
                          currentRange.end = fileLength - 1;
                  } catch (NumberFormatException e) {
                      response.sendError
                          (HttpServletResponse
                           .SC_REQUESTED_RANGE_NOT_SATISFIABLE);
                      return null;
                  }
                  
              }
              
              if (!currentRange.validate()) {
                  response.sendError
                      (HttpServletResponse.SC_REQUESTED_RANGE_NOT_SATISFIABLE);
                  return null;
              }
              
              result.addElement(currentRange);
          }
          
          return result;
      }
  
  
      // ------------------------------------------------------ Range Inner Class
      
      
      private class Range {
          
          public long start;
          public long end;
          public long length;
          
          /**
           * Validate range.
           */
          public boolean validate() {
              return ( (start >= 0) && (end >= 0) && (length > 0)
                       && (start <= end) && (end < length) );
          }
          
      }
      
      
      // ----------------------------------------------  ResourceInfo Inner Class
      
      
      private class ResourceInfo {
          
          
          /**
           * Constructor.
           * 
           * @param pathname Path name of the file
           */
          public ResourceInfo(String path, NodeRevisionDescriptor properties) {
              
              this.path = path;
              this.exists = true;
              this.creationDate = properties.getCreationDateAsDate().getTime();
              this.date = properties.getLastModifiedAsDate().getTime();
              this.httpDate = properties.getLastModified();
              this.length = properties.getContentLength();
              
          }
          
          
          public String path;
          public long creationDate;
          public String httpDate;
          public long date;
          public long length;
          //public boolean collection;
          public boolean exists;
          
          
          /**
           * Test if the associated resource exists.
           */
          public boolean exists() {
              return exists;
          }
          
          
          /**
           * String representation.
           */
          public String toString() {
              return path;
          }
          
          
      }
      
      
  }
  
  
  
  1.1                  jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/HeadMethod.java
  
  Index: HeadMethod.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/HeadMethod.java,v 1.1 2000/11/22 06:20:46 remm Exp $
   * $Revision: 1.1 $
   * $Date: 2000/11/22 06:20:46 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */ 
  
  package org.apache.slide.webdav.method;
  
  import java.security.Principal;
  import java.io.*;
  import java.util.*;
  import javax.servlet.*;
  import javax.servlet.http.*;
  import org.apache.slide.common.*;
  import org.apache.slide.security.AccessDeniedException;
  import org.apache.slide.webdav.common.*;
  import org.apache.slide.webdav.*;
  import org.apache.slide.lock.*;
  import org.apache.slide.structure.*;
  import org.apache.slide.content.*;
  
  /**
   * HEAD method.
   * 
   * @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
   */
  public class HeadMethod extends GetMethod {
      
      
      // ----------------------------------------------------------- Constructors
      
      
      /**
       * HEAD Method constructor.
       * 
       * @param token Namespace access token
       * @param req HTTP request
       * @param resp HTTP response
       */
      public HeadMethod(GenericServlet servlet, NamespaceAccessToken token, 
                        HttpServletRequest req, HttpServletResponse resp) {
  	super(servlet, token, req, resp);
          printContent = false;
      }
      
      
  }
  
  
  
  1.1                  jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/LockMethod.java
  
  Index: LockMethod.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/LockMethod.java,v 1.1 2000/11/22 06:20:46 remm Exp $
   * $Revision: 1.1 $
   * $Date: 2000/11/22 06:20:46 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */ 
  
  package org.apache.slide.webdav.method;
  
  import java.security.Principal;
  import java.io.*;
  import java.util.*;
  import javax.servlet.*;
  import javax.servlet.http.*;
  import org.w3c.dom.*;
  import org.xml.sax.InputSource;
  import org.apache.slide.common.*;
  import org.apache.slide.webdav.common.*;
  import org.apache.slide.webdav.*;
  import org.apache.slide.macro.*;
  import org.apache.slide.lock.*;
  import org.apache.slide.content.*;
  import org.apache.slide.security.AccessDeniedException;
  import org.apache.slide.structure.*;
  import org.apache.slide.util.dom.DOMWriter;
  import javax.xml.parsers.DocumentBuilder;
  
  /**
   * LOCK method.
   * 
   * @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
   */
  public class LockMethod extends WebdavMethod {
      
      
      // -------------------------------------------------------------- Constants
      
      
      /**
       * Default depth is infite.
       */
      private static final int INFINITY = -1;
      
      
      /**
       * Create a new lock.
       */
      private static final int LOCK_CREATION = 0;
      
      
      /**
       * Refresh lock.
       */
      private static final int LOCK_REFRESH = 1;
      
      
      /**
       * Default timeout value.
       */
      private static final int DEFAULT_TIMEOUT = 3600;
      
      
      /**
       * Maximum timeout.
       */
      private static final int MAX_TIMEOUT = 604800;
      
      
      // ----------------------------------------------------- Instance Variables
      
      
      /**
       * Depth.
       */
      private int depth;
      
      
      /**
       * Type of the LOCK method.
       */
      private int lockType;
      
      
      /**
       * Lock duration.
       */
      private int lockDuration;
      
      
      /**
       * DAV Namespace support.
       */
      private boolean davNative;
      
      
      /**
       * MS Proprietary properties support.
       */
      private boolean msProprietarySupport;
      
      
      /**
       * Lock scope.
       */
      private String lockInfo_lockScope;
      
      
      /**
       * Lock type.
       */
      private String lockInfo_lockType;
      
      
      /**
       * Lock owner.
       */
      private String lockInfo_lockOwner;
      
      
      /**
       * Lock subject.
       */
      private String lockInfo_lockSubject;
      
      
      // ----------------------------------------------------------- Constructors
      
      
      /**
       * LOCK method constructor.
       * 
       * @param token Namespace access token
       * @param requestUri Request URI
       * @param principal Principal object, given by the servlet container
       * @param req HTTP request
       * @param resp HTTP response
       */
      public LockMethod(GenericServlet servlet, NamespaceAccessToken token, 
                        HttpServletRequest req, HttpServletResponse resp) {
          super(servlet, token, req, resp);
          readRequestContent();
      }
      
      
      // ------------------------------------------------------ Protected Methods
      
      
      /**
       * Parse request.
       * 
       * @exception WebdavException Does not happen
       */
      protected void parseRequest() 
          throws WebdavException {
          
          // Show request
          if (req.getContentLength() > 0) {
              System.out.println(new String(requestBody));
          }
          
          msProprietarySupport = isMsProprietarySupport();
          
  	// Loads the associated object from the store.
  	lockInfo_lockSubject = requestUri;
  	if (lockInfo_lockSubject == null) {
  	    lockInfo_lockSubject = "/";
  	}
          
  	String depthStr = req.getHeader("Depth");
  	
  	if (depthStr == null) {
  	    depth = INFINITY;
  	} else {
  	    if (depthStr.equals("0")) {
  		depth = 0;
  	    } else {
                  depth = INFINITY;
  	    }
  	}
          
          String lockDurationStr = req.getHeader("Timeout");
          if (lockDurationStr == null) {
              lockDuration = DEFAULT_TIMEOUT;
          } else {
              if (lockDurationStr.startsWith("Second-")) {
                  lockDuration = 
                      (new Integer(lockDurationStr.substring(7))).intValue();
              } else {
                  if (lockDurationStr.equalsIgnoreCase("infinity")) {
                      lockDuration = MAX_TIMEOUT;
                  } else {
                      try {
                          lockDuration = 
                              (new Integer(lockDurationStr)).intValue();
                      } catch (NumberFormatException e) {
                          lockDuration = MAX_TIMEOUT;
                      }
                  }
              }
              if (lockDuration == 0) {
                  lockDuration = DEFAULT_TIMEOUT;
              }
              if (lockDuration > MAX_TIMEOUT) {
                  lockDuration = MAX_TIMEOUT;
              }
          }
          
          // For some strange reason, IIS doesn't handle properly 
          // lock expiration.
          /*
            if (isMsProprietarySupport()) {
            lockDuration = MAX_TIMEOUT;
            }
          */
          
  	if (req.getContentLength() > 0) {
              
              lockType = LOCK_CREATION;
              
              Node lockInfoNode = null;
              
              try {
                  Document document = documentBuilder.parse(new InputSource
                      (new StringReader(new String(requestBody))));
                  
                  // Get the root element of the document
                  Element rootElement = document.getDocumentElement();
                  lockInfoNode = rootElement;
              } catch(Exception e) {
                  e.printStackTrace();
  		resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
  		throw new WebdavException(WebdavStatus.SC_BAD_REQUEST);
              }
              
              NodeList childList = lockInfoNode.getChildNodes();
              StringWriter strWriter = null;
              DOMWriter domWriter = null;
              
              Node lockScopeNode = null;
              Node lockTypeNode = null;
              Node lockOwnerNode = null;
              
              for (int i=0; i < childList.getLength(); i++) {
                  Node currentNode = childList.item(i);
                  switch (currentNode.getNodeType()) {
                  case Node.TEXT_NODE:
                      break;
                  case Node.ELEMENT_NODE:
                      String nodeName = currentNode.getNodeName();
                      if (nodeName.endsWith("lockscope")) {
                          lockScopeNode = currentNode;
                      }
                      if (nodeName.endsWith("locktype")) {
                          lockTypeNode = currentNode;
                      }
                      if (nodeName.endsWith("owner")) {
                          lockOwnerNode = currentNode;
                      }
                      break;
                  }
              }
              
              if (lockScopeNode != null) {
                  
                  childList = lockScopeNode.getChildNodes();
                  for (int i=0; i < childList.getLength(); i++) {
                      Node currentNode = childList.item(i);
                      switch (currentNode.getNodeType()) {
                      case Node.TEXT_NODE:
                          break;
                      case Node.ELEMENT_NODE:
                          String tempScope = currentNode.getNodeName();
                          if (tempScope.indexOf(':') != -1) {
                              lockInfo_lockScope = "<" 
                                  + tempScope.substring(tempScope.indexOf(':') 
                                                        + 1) + "/>";
                          } else {
                              lockInfo_lockScope = "<" + tempScope + "/>";
                          }
                          System.out.println("Lock scope : " 
                                             + lockInfo_lockScope);
                          break;
                      }
                  }
                  
                  if (lockInfo_lockScope == null) {
                      // Bad request
                      resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
                  }
                  
              } else {
                  // Bad request
                  resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
              }
              
              if (lockTypeNode != null) {
                  
                  childList = lockTypeNode.getChildNodes();
                  for (int i=0; i < childList.getLength(); i++) {
                      Node currentNode = childList.item(i);
                      switch (currentNode.getNodeType()) {
                      case Node.TEXT_NODE:
                          break;
                      case Node.ELEMENT_NODE:
                          String tempType = currentNode.getNodeName();
                          if (tempType.indexOf(':') != -1) {
                              lockInfo_lockType = "<" 
                                  + tempType.substring(tempType.indexOf(':') + 1)
                                  + "/>";
                          } else {
                              lockInfo_lockType = "<" + tempType + "/>";
                          }
                          System.out.println("Lock type : " + lockInfo_lockType);
                          break;
                      }
                  }
                  
                  if (lockInfo_lockType == null) {
                      // Bad request
                      resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
                  }
                  
              } else {
                  // Bad request
                  resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
              }
              
              if (lockOwnerNode != null) {
                  
                  childList = lockOwnerNode.getChildNodes();
                  for (int i=0; i < childList.getLength(); i++) {
                      Node currentNode = childList.item(i);
                      switch (currentNode.getNodeType()) {
                      case Node.TEXT_NODE:
                          break;
                      case Node.ELEMENT_NODE:
                          strWriter = new StringWriter();
                          domWriter = new DOMWriter(strWriter, true);
                          domWriter.print(currentNode);
                          lockInfo_lockOwner = strWriter.toString();
                          System.out.println("Lock owner : " 
                                             + lockInfo_lockOwner);
                          break;
                      }
                  }
                  
                  if (lockInfo_lockScope == null) {
                      // Bad request
                      resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
                  }
                  
              } else {
                  lockInfo_lockOwner = new String();
              }
              
          } else {
              lockType = LOCK_REFRESH;
          }
          
      }
      
      
      /**
       * Execute request.
       * 
       * @exception WebdavException Unrecoverable error while renewing lock
       */
      protected void executeRequest() 
          throws WebdavException {
          
          SubjectNode toLockSubject = null;
          
          switch (lockType) {
              
          case LOCK_CREATION:
              
              try {
                  
                  NamespaceConfig namespaceConfig = token.getNamespaceConfig();
                  
                  try {
                      toLockSubject = (SubjectNode) structure
                          .retrieve(credToken, lockInfo_lockSubject);
                  } catch (ObjectNotFoundException ex) {
                      
                      // Creating a lock null resource
                      toLockSubject = new SubjectNode();
                      
                      // Creating new subject
                      structure.create(credToken, toLockSubject, 
                                       lockInfo_lockSubject);
                      
                      NodeRevisionDescriptor revisionDescriptor = 
                          new NodeRevisionDescriptor(0);
                      
                      NodeProperty property = null;
                      
                      // Resource type
                      property = new NodeProperty("resourcetype", 
                                                  "<lock-null/>", true);
                      revisionDescriptor.setProperty(property);
                      
                      // Creating the revision descriptor
                      content.create(credToken, lockInfo_lockSubject, 
                                     revisionDescriptor, null);
                      
                  }
                  
                  SubjectNode credentialsSubject = 
                      (SubjectNode) structure.retrieve
                      (credToken, namespaceConfig.getUsersPath() + "/"
                       + credToken.getPublicCredentials());
                  
                  NodeLock lockToken = null;
                  
                  boolean inheritance = (depth != 0);
                  boolean exclusive = 
                      !(lockInfo_lockScope.equals("<shared/>"));
                  
                  Date lockDate = new Date((new Date()).getTime() 
                                           + (lockDuration * 1000));
                  
                  lockToken = 
                      new NodeLock(toLockSubject, credentialsSubject, 
                                   namespaceConfig.getCreateObjectAction(), 
                                   lockDate, inheritance, exclusive);
                  lock.lock(credToken, lockToken);
                  
                  try {
                      lockToken = new NodeLock
                          (lockToken, 
                           namespaceConfig.getCreateRevisionMetadataAction()
                           .getUri());
                      lock.lock(credToken, lockToken);
                  } catch (ObjectIsAlreadyLockedException e) {
                      // Silent catch
                  }
  
                  try {
                      lockToken = new NodeLock
                          (lockToken, 
                           namespaceConfig.getModifyRevisionMetadataAction()
                           .getUri());
                      lock.lock(credToken, lockToken);
                  } catch (ObjectIsAlreadyLockedException e) {
                      // Silent catch
                  }
                  
                  try {
                      lockToken = new NodeLock
                          (lockToken, 
                           namespaceConfig.getRemoveRevisionMetadataAction()
                           .getUri());
                      lock.lock(credToken, lockToken);
                  } catch (ObjectIsAlreadyLockedException e) {
                      // Silent catch
                  }
                  
                  try {
                      lockToken = new NodeLock
                          (lockToken, 
                           namespaceConfig.getModifyRevisionContentAction()
                           .getUri());
                      lock.lock(credToken, lockToken);
                  } catch (ObjectIsAlreadyLockedException e) {
                      // Silent catch
                  }
                  
                  try {
                      lockToken = new NodeLock
                          (lockToken, 
                           namespaceConfig.getRemoveRevisionContentAction()
                           .getUri());
                      lock.lock(credToken, lockToken);
                  } catch (ObjectIsAlreadyLockedException e) {
                      // Silent catch
                  }
                  
                  try {
                      lockToken = 
                          new NodeLock(lockToken, 
                                       namespaceConfig.getRemoveObjectAction()
                                       .getUri());
                      lock.lock(credToken, lockToken);
                  } catch (ObjectIsAlreadyLockedException e) {
                      // Silent catch
                  }
                  
                  resp.setStatus(WebdavStatus.SC_OK);
                  
                  // The lock token on which the DAV module will have the info
                  
                  showLockDiscoveryInfo(lockToken);
                  
              } catch (ObjectIsAlreadyLockedException e) {
                  resp.setStatus(WebdavStatus.SC_LOCKED);
                  e.printStackTrace();
              } catch (SlideException e) {
                  resp.setStatus(WebdavStatus.SC_PRECONDITION_FAILED);
                  e.printStackTrace();
              }
              
              break;
              
          case LOCK_REFRESH:
              
              try {
                  
                  Enumeration lockTokens = 
                      lock.enumerateLocks(credToken, lockInfo_lockSubject);
                  
                  NodeLock currentLockToken = null;
                  Date newExpirationDate = 
                      new Date((new Date()).getTime() + (lockDuration * 1000));
                  while (lockTokens.hasMoreElements()) {
                      currentLockToken = (NodeLock) lockTokens.nextElement();
                      lock.renew(credToken, currentLockToken, newExpirationDate);
                  }
                  
                  showLockDiscoveryInfo(currentLockToken);
                  
              } catch (SlideException e) {
                  resp.setStatus(WebdavStatus.SC_PRECONDITION_FAILED);
                  e.printStackTrace();
              }
              
              break;
              
          }
          
      }
      
      
      /**
       * Show lockdiscovery info.
       * 
       * @exception WebdavException Something is wrong with the servlet container
       */
      protected void showLockDiscoveryInfo(NodeLock token) 
          throws WebdavException {
          
          // Generating XML response
          
          WebdavXMLPrinter generatedXML = new WebdavXMLPrinter();
          
          generatedXML.writeXMLHeader();
          generatedXML.writeElement("d", "DAV:", "prop", 
                                    WebdavXMLPrinter.OPENING);
          
          generatedXML.writeElement("d", null, "lockdiscovery", 
                                    WebdavXMLPrinter.OPENING);
          
          generatedXML.writeElement("d", null, "activelock", 
                                    WebdavXMLPrinter.OPENING);
          
          generatedXML.writeElement("d", null, "locktype", 
                                    WebdavXMLPrinter.OPENING);
          generatedXML.writeElement("d", null, "write", 
                                    WebdavXMLPrinter.NO_CONTENT);
          generatedXML.writeElement("d", null, "locktype", 
                                    WebdavXMLPrinter.CLOSING);
          
          generatedXML.writeElement("d", null, "lockscope", 
                                    WebdavXMLPrinter.OPENING);
          
          if (token.isExclusive()) {
              generatedXML.writeElement("d", null, "exclusive", 
                                        WebdavXMLPrinter.NO_CONTENT);
          } else {
              generatedXML.writeElement("d", null, "shared", 
                                        WebdavXMLPrinter.NO_CONTENT);
          }
          generatedXML.writeElement("d", null, "lockscope", 
                                    WebdavXMLPrinter.CLOSING);
          
          generatedXML.writeElement("d", null, "depth", 
                                    WebdavXMLPrinter.OPENING);
          if (token.isInheritable()) {
              generatedXML.writeText("Infinity");
          } else {
              generatedXML.writeText("0");
          }
          generatedXML.writeElement("d", null, "depth", 
                                    WebdavXMLPrinter.CLOSING);
          
          generatedXML.writeElement("d", null, "owner", 
                                    WebdavXMLPrinter.OPENING);
          //generatedXML.writeText(lockInfo_lockOwner);
          generatedXML.writeText(req.getServletPath() + token.getSubjectUri());
          generatedXML.writeElement("d", null, "owner", 
                                    WebdavXMLPrinter.CLOSING);
          
          generatedXML.writeElement("d", null, "timeout", 
                                    WebdavXMLPrinter.OPENING);
          generatedXML.writeText("Second-" 
                                 + (new Long((token.getExpirationDate().getTime()
                                              - (new Date()).getTime())/1000))
                                 .toString());
          generatedXML.writeElement("d", null, "timeout", 
                                    WebdavXMLPrinter.CLOSING);
          
          generatedXML.writeElement("d", null, "locktoken", 
                                    WebdavXMLPrinter.OPENING);
          generatedXML.writeElement("d", null, "href", 
                                    WebdavXMLPrinter.OPENING);
          // Put here the token Id
          generatedXML.writeText("opaquelocktoken:" + token.getLockId());
          
          generatedXML.writeElement("d", null, "href", 
                                    WebdavXMLPrinter.CLOSING);
          generatedXML.writeElement("d", null, "locktoken", 
                                    WebdavXMLPrinter.CLOSING);
          
          generatedXML.writeElement("d", null, "activelock", 
                                    WebdavXMLPrinter.CLOSING);
          
          generatedXML.writeElement("d", null, "lockdiscovery", 
                                    WebdavXMLPrinter.CLOSING);
          
          generatedXML.writeElement("d", null, "prop", 
                                    WebdavXMLPrinter.CLOSING);
          
          try {
              System.out.println("Query result");
              
              System.out.println(generatedXML.toString());
              
              Writer writer = resp.getWriter();
              writer.write(generatedXML.toString());
              writer.flush();
          } catch (Exception e) {
              e.printStackTrace();
              throw new WebdavException(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
          }
          
      }
      
  }
  
  
  
  1.1                  jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/MkcolMethod.java
  
  Index: MkcolMethod.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/MkcolMethod.java,v 1.1 2000/11/22 06:20:46 remm Exp $
   * $Revision: 1.1 $
   * $Date: 2000/11/22 06:20:46 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */ 
  
  package org.apache.slide.webdav.method;
  
  import java.security.Principal;
  import java.io.*;
  import java.util.*;
  import java.text.DateFormat;
  import java.text.SimpleDateFormat;
  import javax.servlet.*;
  import javax.servlet.http.*;
  import org.apache.slide.common.*;
  import org.apache.slide.webdav.common.*;
  import org.apache.slide.webdav.*;
  import org.apache.slide.structure.*;
  import org.apache.slide.content.*;
  import org.apache.slide.lock.*;
  import org.apache.slide.security.AccessDeniedException;
  
  /**
   * MKCOL method.
   * 
   * @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
   */
  public class MkcolMethod extends WebdavMethod {
      
      
      // -------------------------------------------------------------- Constants
      
      
      /**
       * HTTP Date format pattern (RFC 2068, 822, 1123).
       */
      public static final String DATE_FORMAT = "EEE, d MMM yyyy kk:mm:ss z";
      
      
      // ----------------------------------------------------- Instance Variables
      
      
      /**
       * Collection name.
       */
      private String colName;
      
      
      // ----------------------------------------------------------- Constructors
      
      
      /**
       * GET Method constructor.
       * 
       * @param token Namespace access token
       * @param req HTTP request
       * @param resp HTTP response
       */
      public MkcolMethod(GenericServlet servlet, NamespaceAccessToken token, 
                         HttpServletRequest req, HttpServletResponse resp) {
  	super(servlet, token, req, resp);
      }
      
      
      // ------------------------------------------------------ Protected Methods
      
      
      /**
       * Parse XML request.
       */
      protected void parseRequest() 
  	throws WebdavException {
  	colName = requestUri;
  	if (colName == null) {
  	    colName = "/";
  	}
      }
      
      
      /**
       * Execute request.
       * 
       * @exception WebdavException Bad request
       */
      protected void executeRequest() 
          throws WebdavException {
          
          SubjectNode collection = new SubjectNode();
          NodeRevisionDescriptor revisionDescriptor = 
              new NodeRevisionDescriptor(0);
          
          NodeProperty property = null;
          
          // Resource type
          property = new NodeProperty("resourcetype", "<collection/>", true);
          revisionDescriptor.setProperty(property);
          
          // Creation date
          DateFormat formatter = new SimpleDateFormat(DATE_FORMAT);
          property = new NodeProperty("creationdate", 
                                      formatter.format(new Date()), true);
          revisionDescriptor.setProperty(property);
          
          // Last modification date
          property = new NodeProperty("getlastmodified", 
                                      formatter.format(new Date()), true);
          revisionDescriptor.setProperty(property);
          
          // Display name
          property = new NodeProperty("displayname", colName, true);
          revisionDescriptor.setProperty(property);
          
          // Display name
          property = new NodeProperty("getcontentlength", "0", true);
          revisionDescriptor.setProperty(property);
          
          // Source
          property = new NodeProperty("source", "", true);
          revisionDescriptor.setProperty(property);
          
          if (isMsProprietarySupport()) {
              
              // Name
              /*
                property = new NodeProperty("name", colName, "ms", "MICROSOFT");
                properties.setProperty(property);
              */
              
              // ParentName
              // TODO : Fix this
              /*
                property = new NodeProperty("parentname", colName, "ms", 
                "MICROSOFT");
                properties.setProperty(property);
              */
              
              // Href
              /*
                property = new NodeProperty("href", colName, "ms", "MICROSOFT");
                properties.setProperty(property);
              */
              
              // Is hidden
              property = new NodeProperty("ishidden", "0", "MICROSOFT");
              revisionDescriptor.setProperty(property);
              
              // Is collection
              property = new NodeProperty("iscollection", "1", "MICROSOFT");
              revisionDescriptor.setProperty(property);
              
              // Is read only
              property = new NodeProperty("isreadonly", "0", "MICROSOFT");
              revisionDescriptor.setProperty(property);
              
              // Last accessed
              property = new NodeProperty("lastaccessed", 
                                          (new Date()).toString(), "MICROSOFT");
              revisionDescriptor.setProperty(property);
              
          }
          
          try {
              structure.create(credToken, collection, colName);
              content.create(credToken, colName, revisionDescriptor, null);
          } catch (ObjectNotFoundException e) {
  	    resp.setStatus(WebdavStatus.SC_CONFLICT);
  	    throw new WebdavException(WebdavStatus.SC_CONFLICT);
  	} catch (ObjectLockedException e) {
  	    resp.setStatus(WebdavStatus.SC_LOCKED);
  	    throw new WebdavException(WebdavStatus.SC_LOCKED);
  	} catch (RevisionAlreadyExistException e) {
  	    resp.setStatus(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
  	    throw new WebdavException(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
  	} catch (ServiceAccessException e) {
  	    resp.setStatus(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
  	    throw new WebdavException(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
  	} catch (LinkedObjectNotFoundException e) {
  	    resp.setStatus(WebdavStatus.SC_NOT_FOUND);
  	    throw new WebdavException(WebdavStatus.SC_NOT_FOUND);
  	} catch (ObjectAlreadyExistsException e) {
              resp.setStatus(WebdavStatus.SC_METHOD_NOT_ALLOWED);
              throw new WebdavException(WebdavStatus.SC_METHOD_NOT_ALLOWED);
          } catch (AccessDeniedException e) {
  	    resp.setStatus(WebdavStatus.SC_FORBIDDEN);
  	    //throw new WebdavException(WebdavStatus.SC_FORBIDDEN);
  	}
  	
  	// 415 - Unsupported Media Type
  	// TODO : Has something to do with the body of the request ...
  	// WebDAV RFC is vague on the subject.
  	
  	// 507 - Insufficient storage
  	// Would be returned as a ServiceAccessException, so it would 
          // return an Internal Server Error, which is probably acceptable.
  	
  	// TODO : Initialize and create collection's properties.
  	
          // 201 - Created / OK
          resp.setStatus(WebdavStatus.SC_CREATED);
  	
      }
      
  }
  
  
  
  1.1                  jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/MoveMethod.java
  
  Index: MoveMethod.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/MoveMethod.java,v 1.1 2000/11/22 06:20:46 remm Exp $
   * $Revision: 1.1 $
   * $Date: 2000/11/22 06:20:46 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */ 
  
  package org.apache.slide.webdav.method;
  
  import java.security.Principal;
  import java.io.*;
  import java.util.*;
  import javax.servlet.*;
  import javax.servlet.http.*;
  import org.apache.slide.common.*;
  import org.apache.slide.webdav.common.*;
  import org.apache.slide.webdav.*;
  import org.apache.slide.macro.*;
  import org.apache.slide.lock.*;
  import org.apache.slide.content.*;
  import org.apache.slide.security.AccessDeniedException;
  import org.apache.slide.structure.*;
  
  /**
   * MOVE Method.
   * 
   * @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
   */
  public class MoveMethod extends WebdavMethod {
      
      
      // ----------------------------------------------------- Instance Variables
      
      
      /**
       * Id of the resosurce or collection which is to be move.
       */
      private String sourceUri;
      
      /**
       * Uri of the target.
       */
      private String destinationUri;
      
      /**
       * Overwrite.
       */
      private boolean overwrite;
      
      
      // ----------------------------------------------------------- Constructors
      
      
      /**
       * MOVE method constructor.
       * 
       * @param token Namespace access token
       * @param req HTTP request
       * @param resp HTTP response
       */
      public MoveMethod(GenericServlet servlet, NamespaceAccessToken token, 
                        HttpServletRequest req, HttpServletResponse resp) {
          super(servlet, token, req, resp);
      }
      
      
      // ------------------------------------------------------ Protected Methods
      
      
      /**
       * Parse request.
       *
       * @exception WebdavException Does not happen
       */
      protected void parseRequest() 
          throws WebdavException {
          
          sourceUri = requestUri;
          if (sourceUri == null) {
              sourceUri = "/";
          }
          
          destinationUri = req.getHeader("Destination");
          
          String HTTPHeader = "http://";
          if (destinationUri.startsWith(HTTPHeader)) {
              destinationUri = destinationUri.substring(HTTPHeader.length());
          }
          
          String hostName = req.getServerName();
          if ((hostName != null) && (destinationUri.startsWith(hostName))) {
              destinationUri = destinationUri.substring(hostName.length());
          }
          
          if (destinationUri.startsWith(":")) {
              int firstSeparator = destinationUri.indexOf("/");
              if (firstSeparator < 0) {
                  destinationUri = "/";
              } else {
                  destinationUri = destinationUri.substring(firstSeparator);
              }
          }
          
          String contextPath = req.getContextPath();
          if ((contextPath != null) && 
              (destinationUri.startsWith(contextPath))) {
              destinationUri = destinationUri.substring(contextPath.length());
          }
          
          String pathInfo = req.getPathInfo();
          if (pathInfo != null) {
              String servletPath = req.getServletPath();
              if ((servletPath != null) && 
                  (destinationUri.startsWith(servletPath))) {
                  destinationUri = destinationUri
                      .substring(servletPath.length());
              }
          }
          
          String overwriteHeader = req.getHeader("Overwrite");
          
          if (overwriteHeader != null) {
              if (overwriteHeader.equalsIgnoreCase("T")) {
                  overwrite = true;
              } else {
                  overwrite = false;
              }
          } else {
              overwrite = true;
          }
          
      }
      
      
      /**
       * Execute request.
       * 
       * @exception WebdavException Unrecoverable error while moving the files
       */
      protected void executeRequest() 
          throws WebdavException {
          
          MacroParameters macroParameters = null;
          
          if (overwrite) {
              macroParameters = Macro.RECURSIVE_OVERWRITE_PARAMETERS;
          } else {
              macroParameters = Macro.DEFAULT_PARAMETERS;
          }
          
          try {
              macro.move(credToken, sourceUri, destinationUri, macroParameters);
              if (overwrite) {
                  resp.setStatus(WebdavStatus.SC_NO_CONTENT);
              } else {
                  resp.setStatus(WebdavStatus.SC_CREATED);
              }
          } catch (DeleteMacroException e) {
              String errorMessage = generateErrorMessage(e);
              // Write it on the servlet writer
              resp.setStatus(WebdavStatus.SC_MULTI_STATUS);
              try {
                  resp.getWriter().write(errorMessage);
              } catch(IOException ex) {
                  // Critical error ... Servlet container is dead or something
                  ex.printStackTrace();
                  throw new WebdavException
                      (WebdavStatus.SC_INTERNAL_SERVER_ERROR);
              }
          } catch (CopyMacroException e) {
              String errorMessage = generateErrorMessage(e);
              // Write it on the servlet writer
              resp.setStatus(WebdavStatus.SC_MULTI_STATUS);
              try {
                  resp.getWriter().write(errorMessage);
              } catch(IOException ex) {
                  // Critical error ... Servlet container is dead or something
                  ex.printStackTrace();
                  throw new WebdavException
                      (WebdavStatus.SC_INTERNAL_SERVER_ERROR);
              }
          }
          
      }
      
      
      /**
       * Generate an XML error message.
       * 
       * @param macroException Nested exception
       * @return String XML message
       */
      protected String generateErrorMessage(MacroException macroException) {
          
          WebdavXMLPrinter errorMessage = new WebdavXMLPrinter();
          
          errorMessage.writeXMLHeader();
          errorMessage.writeElement("d", "DAV", "multistatus", 
                                    WebdavXMLPrinter.OPENING);
          
          Enumeration nestedExceptionsList = 
              macroException.enumerateExceptions();
          
          while (nestedExceptionsList.hasMoreElements()) {
              
              errorMessage.writeElement("d", "DAV", "response", 
                                        WebdavXMLPrinter.OPENING);
              
              SlideException ex = 
                  (SlideException) nestedExceptionsList.nextElement();
              
              String status = new String();
              
              try {
                  throw ex;
              } catch(ObjectNotFoundException e) {
                  generateStatusText(errorMessage, e.getObjectUri(), 
                                     WebdavStatus.SC_INTERNAL_SERVER_ERROR);
              } catch(AccessDeniedException e) {
                  generateStatusText(errorMessage, e.getObjectUri(), 
                                     WebdavStatus.SC_FORBIDDEN);
              } catch(ObjectAlreadyExistsException e) {
                  generateStatusText(errorMessage, e.getObjectUri(), 
                                     WebdavStatus.SC_INTERNAL_SERVER_ERROR);
              } catch(ServiceAccessException e) {
                  generateStatusText(errorMessage, e.getMessage(), 
                                     WebdavStatus.SC_BAD_GATEWAY);
              } catch(LinkedObjectNotFoundException e) {
                  generateStatusText(errorMessage, e.getTargetUri(), 
                                     WebdavStatus.SC_INTERNAL_SERVER_ERROR);
              } catch(RevisionNotFoundException e) {
                  generateStatusText(errorMessage, e.getObjectUri(), 
                                     WebdavStatus.SC_INTERNAL_SERVER_ERROR);
              } catch(ObjectLockedException e) {
                  generateStatusText(errorMessage, e.getObjectUri(), 
                                     WebdavStatus.SC_LOCKED);
              } catch(SlideException e) {
                  generateStatusText(errorMessage, e.getMessage(), 
                                     WebdavStatus.SC_INTERNAL_SERVER_ERROR);
              }
              
              errorMessage.writeElement("d", "DAV", "response", 
                                        WebdavXMLPrinter.CLOSING);
              
          }
          
          errorMessage.writeElement("d", "DAV", "multistatus", 
                                    WebdavXMLPrinter.CLOSING);
          
          return errorMessage.toString();
          
      }
      
      
      /**
       * Generate status text.
       * 
       * @param printer XML Printer
       * @param href Uri of the object
       * @param statusCode HTTP status code of the error
       */
      protected void generateStatusText(WebdavXMLPrinter printer, String href, 
                                        int statusCode) {
          printer.writeElement("d", "href", WebdavXMLPrinter.OPENING);        
          printer.writeText(href);
          printer.writeElement("d", "href", WebdavXMLPrinter.CLOSING);
          printer.writeElement("d", "status", WebdavXMLPrinter.OPENING);        
          printer.writeText("HTTP/1.1 " + statusCode + " " 
                            + WebdavStatus.getStatusText(statusCode));
          printer.writeElement("d", "status", WebdavXMLPrinter.CLOSING);
      }
      
  }
  
  
  
  1.1                  jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/OptionsMethod.java
  
  Index: OptionsMethod.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/OptionsMethod.java,v 1.1 2000/11/22 06:20:46 remm Exp $
   * $Revision: 1.1 $
   * $Date: 2000/11/22 06:20:46 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */ 
  
  package org.apache.slide.webdav.method;
  
  import java.security.Principal;
  import java.io.*;
  import java.util.*;
  import javax.servlet.*;
  import javax.servlet.http.*;
  import org.apache.slide.authenticate.CredentialsToken;
  import org.apache.slide.common.*;
  import org.apache.slide.security.AccessDeniedException;
  import org.apache.slide.webdav.common.*;
  import org.apache.slide.webdav.*;
  import org.apache.slide.structure.*;
  import org.apache.slide.lock.*;
  import org.apache.slide.content.*;
  
  /**
   * OPTIONS Method.
   * 
   * @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
   */
  public class OptionsMethod extends WebdavMethod {
      
      
      // ----------------------------------------------------------- Constructors
      
      
      public OptionsMethod(GenericServlet servlet, NamespaceAccessToken token, 
                           HttpServletRequest req, HttpServletResponse resp) {
  	super(servlet, token, req, resp);
      }
      
      protected void parseRequest() 
  	throws WebdavException {
      }
      
      protected void executeRequest() 
  	throws WebdavException {
  	resp.addHeader("DAV", "1,2");
          
  	String resourceUri = requestUri;
  	if (resourceUri == null) {
  	    resourceUri = "/";
  	}
          
          String methodsAllowed = null;
          
          try {
              NodeRevisionDescriptors revisionDescriptors = 
                  content.retrieve(credToken, resourceUri);
              NodeRevisionDescriptor revisionDescriptor = 
                  content.retrieve(credToken, revisionDescriptors);
              boolean isCollection = isCollection(revisionDescriptor);
              methodsAllowed = "OPTIONS, GET, HEAD, POST, DELETE, TRACE, " 
                  + "PROPFIND, PROPPATCH, COPY, MOVE, LOCK, UNLOCK";
              if (!isCollection) {
                  methodsAllowed = methodsAllowed + ", PUT";
              }
          } catch (SlideException e) {
              if (resourceUri.equals("/")) {
                  methodsAllowed = "OPTIONS, GET, HEAD, POST, DELETE, TRACE, " 
                      + "PROPFIND, PROPPATCH, COPY, MOVE, LOCK, UNLOCK";
              } else {
                  methodsAllowed = "OPTIONS, MKCOL, PUT, LOCK";
              }
          }
          
          resp.addHeader("Allow", methodsAllowed);
      }
      
  }
  
  
  
  1.1                  jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/PostMethod.java
  
  Index: PostMethod.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/PostMethod.java,v 1.1 2000/11/22 06:20:46 remm Exp $
   * $Revision: 1.1 $
   * $Date: 2000/11/22 06:20:46 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */ 
  
  package org.apache.slide.webdav.method;
  
  import org.apache.slide.common.*;
  import org.apache.slide.webdav.common.*;
  import org.apache.slide.webdav.*;
  import java.security.Principal;
  import java.io.*;
  import java.util.*;
  import javax.servlet.*;
  import javax.servlet.http.*;
  
  /**
   * POST method.
   * 
   * @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
   */
  public class PostMethod extends WebdavMethod {
      
      
      // ----------------------------------------------------------- Constructors
      
      
      public PostMethod(GenericServlet servlet, NamespaceAccessToken token, 
                        HttpServletRequest req, HttpServletResponse resp) {
  	super(servlet, token, req, resp);
      }
      
      protected void parseRequest() 
  	throws WebdavException {
  	// Don't know what to do there.
  	// RFC is extremely vague on the subject ...
      }
      
      protected void executeRequest() 
  	throws WebdavException {
      }
      
  }
  
  
  
  1.1                  jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/PropFindMethod.java
  
  Index: PropFindMethod.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/PropFindMethod.java,v 1.1 2000/11/22 06:20:46 remm Exp $
   * $Revision: 1.1 $
   * $Date: 2000/11/22 06:20:46 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */ 
  
  package org.apache.slide.webdav.method;
  
  import java.security.Principal;
  import java.io.*;
  import java.util.*;
  import javax.servlet.*;
  import javax.servlet.http.*;
  import org.w3c.dom.*;
  import org.xml.sax.InputSource;
  import org.apache.slide.authenticate.CredentialsToken;
  import org.apache.slide.common.*;
  import org.apache.slide.security.AccessDeniedException;
  import org.apache.slide.webdav.common.*;
  import org.apache.slide.webdav.*;
  import org.apache.slide.structure.*;
  import org.apache.slide.lock.*;
  import org.apache.slide.content.*;
  import javax.xml.parsers.DocumentBuilder;
  
  /**
   * PROPFIND method.
   * 
   * @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
   */
  public final class PropFindMethod extends WebdavMethod {
      
      
      // -------------------------------------------------------------- Constants
      
      
      /**
       * Root node URI.
       */
      private static final String DIRECTORY = "/";
      
      
      /**
       * Default depth is infite.
       */
      private static final int INFINITY = 3; // To limit tree browsing a bit
      
      
      /**
       * Specify a property mask.
       */
      private static final int FIND_BY_PROPERTY = 0;
      
      
      /**
       * Display all properties.
       */
      private static final int FIND_ALL_PROP = 1;
      
      
      /**
       * Return property names.
       */
      private static final int FIND_PROPERTY_NAMES = 2;
      
      
      /**
       * Supported locks property value.
       */
      private static final String SUPPORTED_LOCK = "<lockentry>" 
          + "<lockscope><exclusive/></lockscope>"
          + "<locktype><write/></locktype>"
          + "</lockentry>"
          + "<lockentry>" 
          + "<lockscope><shared/></lockscope>"
          + "<locktype><write/></locktype>"
          + "</lockentry>";
      
      
      // ----------------------------------------------------- Instance Variables
      
      
      /**
       * Depth.
       */
      private int depth;
      
      
      /**
       * Type of the PROPFIND method.
       */
      private int propFindType;
      
      
      /**
       * Properties to display 
       */
      private Vector propertyVector;
      
      
      /**
       * MS Proprietary properties support.
       */
      private boolean msProprietarySupport;
      
      
      /**
       * Current namespace number used to generate namespace abbreviations.
       */
      private int namespaceNumber = 0;
      
      
      /**
       * Namespaces list. Keyed by namespace names.
       */
      private Hashtable namespaceAbbrevs;
      
      
      // ----------------------------------------------------------- Constructors
      
      
      /**
       * PROPFIND method constructor.
       * 
       * @param token Namespace access token
       * @param req HTTP request
       * @param resp HTTP response
       */
      public PropFindMethod(GenericServlet servlet, NamespaceAccessToken token, 
                            HttpServletRequest req, HttpServletResponse resp) {
          super(servlet, token, req, resp);
          readRequestContent();
          
          namespaceAbbrevs = new Hashtable();
          depth = INFINITY;
          propFindType = FIND_ALL_PROP;
      }
      
      
      // ------------------------------------------------------ Protected Methods
      
      
      /**
       * Parse the request.
       * 
       * @exception WebdavException Bad request
       */
      protected void parseRequest() 
  	throws WebdavException {
  	
          msProprietarySupport = isMsProprietarySupport();
          
  	String depthStr = req.getHeader("Depth");
  	
  	if (depthStr == null) {
  	    depth = INFINITY;
  	} else {
  	    if (depthStr.equals("0")) {
                  depth = 0;
  	    }
  	    if (depthStr.equals("1")) {
                  depth = 1;
  	    }
  	    if (depthStr.equals("infinity")) {
                  depth = INFINITY;
  	    }
  	}
          
  	if (req.getContentLength() != 0) {
  	    
              //Propfind propfind = null;
              
              // Workaround : Castor doesn't work, so I use DOM in the meantime
              
              Node propNode = null;
              
              try {
                  Document document = 
                      documentBuilder.parse(new InputSource
                          (new StringReader(new String(requestBody))));
                  
                  // Get the root element of the document
                  Element rootElement = document.getDocumentElement();
                  NodeList childList = rootElement.getChildNodes();
                  
                  parseNodeNamespaceDeclarations(rootElement);
                  
                  for (int i=0; i < childList.getLength(); i++) {
                      Node currentNode = childList.item(i);
                      switch (currentNode.getNodeType()) {
                      case Node.TEXT_NODE:
                          break;
                      case Node.ELEMENT_NODE:
                          parseNodeNamespaceDeclarations(currentNode);
                          if (currentNode.getNodeName().endsWith("prop")) {
                              propFindType = FIND_BY_PROPERTY;
                              propNode = currentNode;
                          }
                          if (currentNode.getNodeName().endsWith("propname")) {
                              propFindType = FIND_PROPERTY_NAMES;
                          }
                          if (currentNode.getNodeName().endsWith("allprop")) {
                              propFindType = FIND_ALL_PROP;
                          }
                          break;
                      }
                  }
              } catch(Exception e) {
                  e.printStackTrace();
                  resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
                  throw new WebdavException(WebdavStatus.SC_BAD_REQUEST);
              }
              
              if (propFindType == FIND_BY_PROPERTY) {
                  propertyVector = new Vector();
                  NodeList childList = propNode.getChildNodes();
                  
                  for (int i=0; i < childList.getLength(); i++) {
                      Node currentNode = childList.item(i);
                      switch (currentNode.getNodeType()) {
                      case Node.TEXT_NODE:
                          break;
                      case Node.ELEMENT_NODE:
                          parseNodeNamespaceDeclarations(currentNode);
                          Property property = getProperty(currentNode);
                          propertyVector.addElement(property);
                          break;
                      }
                  }
                  
              }
              
  	}
  	
      }
      
      
      /**
       * Execute the request.
       * 
       * @exception WebdavException 
       */
      protected void executeRequest() 
  	throws WebdavException {
  	
          resp.setStatus(WebdavStatus.SC_MULTI_STATUS);
          
  	// Loads the associated object from the store.
  	String resourceUri = requestUri;
          
          // Get the object from Data.
          ObjectNode resource = null;
          
          try {
              resource = structure.retrieve(credToken, resourceUri);
          } catch (StructureException e) {
              // We silently catch that since we need to generate some XML ...
              e.printStackTrace();
              try {
                  resp.sendError
                      (WebdavStatus.SC_NOT_FOUND, 
                       WebdavStatus.getStatusText(WebdavStatus.SC_NOT_FOUND));
              } catch(IOException ex) {
                  ex.printStackTrace();
              }
              throw new WebdavException(WebdavStatus.SC_NOT_FOUND);
          } catch (ServiceAccessException e) {
              e.printStackTrace();
              resp.setStatus(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
              throw new WebdavException(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
          } catch (AccessDeniedException e) {
              resp.setStatus(WebdavStatus.SC_FORBIDDEN);
              throw new WebdavException(WebdavStatus.SC_FORBIDDEN);
          } catch (Exception e) {
              e.printStackTrace();
          }
          
          // Create multistatus object
          WebdavXMLPrinter generatedXML = new WebdavXMLPrinter();
          
          generatedXML.writeXMLHeader();
          generatedXML.writeElement(null, "multistatus" 
                                    + generateNamespaceDeclarations(), 
                                    WebdavXMLPrinter.OPENING);
          
          if (resource != null) {
              if (depth == 0) {
                  parsePropertiesOfObject(resource, generatedXML);
              } else {
                  // The stack always contains the object of the current level
                  Stack stack = new Stack();
                  stack.push(resource);
                  
                  // Stack of the objects one level below
                  Stack stackBelow = new Stack();
                  
                  while ((!stack.isEmpty()) && (depth >= 0)) {
                      ObjectNode cur = (ObjectNode) stack.pop();
                      parsePropertiesOfObject(cur, generatedXML);
                      
                      Enumeration enum = null;
                      
                      try {
                          enum = structure.getChildren(credToken, cur);
                      } catch (StructureException e) {
                          resp.setStatus(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
                          throw new WebdavException
                              (WebdavStatus.SC_INTERNAL_SERVER_ERROR);
                      } catch (ServiceAccessException e) {
                          resp.setStatus(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
                          throw new WebdavException
                              (WebdavStatus.SC_INTERNAL_SERVER_ERROR);
                      }
                      
                      while (enum.hasMoreElements()) {
                          stackBelow.push(enum.nextElement());
                      }
                      
                      if (stack.isEmpty()) {
                          depth--;
                          stack = stackBelow;
                          stackBelow = new Stack();
                      }
                      
                  }
              }
          }
          
          generatedXML.writeElement(null, "multistatus", 
                                    WebdavXMLPrinter.CLOSING);
          
  	try {
              //System.out.println("Query result");
              //System.out.println(generatedXML.toString());
              
  	    Writer writer = resp.getWriter();
              writer.write(generatedXML.toString());
  	    writer.flush();
  	} catch (Exception e) {
              e.printStackTrace();
  	    throw new WebdavException(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
  	}
          
      }
      
      
      /**
       * Parse properties of an object.
       * 
       * @param object 
       * @param multistatus 
       * @exception WebdavException 
       */
      protected void parsePropertiesOfObject(ObjectNode object, 
                                             WebdavXMLPrinter generatedXML)
  	throws WebdavException {
          
          generatedXML.writeElement(null, "response", WebdavXMLPrinter.OPENING);
          
          String status = new String("HTTP/1.1 " + WebdavStatus.SC_OK + " " 
                                     + WebdavStatus.getStatusText
                                     (WebdavStatus.SC_OK));
          NodeRevisionDescriptors revisionDescriptors = null;
          NodeRevisionDescriptor revisionDescriptor = null;
          
          boolean isCollection = false;
          
          NodeLock objectLockToken = null;
          
          try {
              generatedXML.writeElement(null, "href", WebdavXMLPrinter.OPENING);
              revisionDescriptors = content.retrieve(credToken, object.getUri());
              
              try {
                  
                  revisionDescriptor = content.retrieve(credToken, 
                                                        revisionDescriptors);
                  isCollection = isCollection(revisionDescriptor);
                  
                  String path = object.getUri();
                  
                  String absoluteUri = req.getRequestURI();
                  String relativePath = requestUri;
                  String toAppend = "";
                  if (relativePath.length() <= path.length()) {
                      toAppend = path.substring(relativePath.length());
                      if ((!absoluteUri.endsWith("/")) && 
                          (!toAppend.startsWith("/"))) {
                          toAppend = "/" + toAppend;
                      }
                      if (toAppend.equals("/")) {
                          toAppend = "";
                      }
                  }
                  
                  generatedXML.writeText(absoluteUri + toAppend);
                  
              } catch (RevisionDescriptorNotFoundException e) {
                  
                  // The object doesn't have any revision, we create a dummy 
                  // NodeRevisionDescriptor object
                  isCollection = true;
                  revisionDescriptor = new NodeRevisionDescriptor(0);
                  revisionDescriptor.setName(object.getUri());
                  
                  String path = object.getUri();
                  
                  String absoluteUri = req.getRequestURI();
                  String relativePath = requestUri;
                  String toAppend = "";
                  if (relativePath.length() <= path.length()) {
                      toAppend = path.substring(relativePath.length());
                      if ((!absoluteUri.endsWith("/")) 
                          && (!toAppend.startsWith("/"))) {
                          toAppend = "/" + toAppend;
                      }
                  }
                  
                  generatedXML.writeText(absoluteUri + toAppend);
                  
              }
              
              generatedXML.writeElement(null, "href", WebdavXMLPrinter.CLOSING);
              
              Enumeration lockTokens = lock.enumerateLocks(credToken, 
                                                           object.getUri());
              
              if (lockTokens.hasMoreElements()) {
                  objectLockToken = (NodeLock) lockTokens.nextElement();
              }
              
          } catch (ServiceAccessException e) {
              e.printStackTrace();
              resp.setStatus(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
              throw new WebdavException(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
          } catch (AccessDeniedException e) {
              if (revisionDescriptor == null) {
                  revisionDescriptor = new NodeRevisionDescriptor(0);
              }
          } catch (SlideException e) {
              e.printStackTrace();
              resp.setStatus(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
              throw new WebdavException(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
          }
          
          Vector propertiesParser = null;
          
          switch (propFindType) {
          case FIND_ALL_PROP :
              
              // Show properties / values for current object.
              generatedXML.writeElement(null, "propstat", 
                                        WebdavXMLPrinter.OPENING);
              generatedXML.writeElement(null, "prop", WebdavXMLPrinter.OPENING);
              
              status = new String("HTTP/1.1 " + WebdavStatus.SC_OK 
                                  + " " + WebdavStatus.getStatusText
                                  (WebdavStatus.SC_OK));
              
              // Lock information, which is dynamically generated
              if (objectLockToken != null) {
                  showLockDiscoveryInfo(objectLockToken, generatedXML);
              }
              
              // Supported locks
              generatedXML.writeElement(null, "supportedlock", 
                                        WebdavXMLPrinter.OPENING);
              generatedXML.writeText(SUPPORTED_LOCK);
              generatedXML.writeElement(null, "supportedlock", 
                                        WebdavXMLPrinter.CLOSING);
              
              // Other properties
              Enumeration propertyList = 
                  revisionDescriptor.enumerateProperties();
              
              while (propertyList.hasMoreElements()) {
                  NodeProperty currentProperty = 
                      (NodeProperty) propertyList.nextElement();
                  if (currentProperty != null) {
                      String namespace = currentProperty.getNamespace();
                      String namespaceAbbrev = 
                          (String) namespaceAbbrevs.get(namespace);
                      Object currentPropertyValue = currentProperty.getValue();
                      if ((currentPropertyValue == null) || 
                          (currentPropertyValue.toString().equals(""))) {
                          generatedXML.writeElement
                              (namespaceAbbrev, namespace,
                               currentProperty.getName(), 
                               WebdavXMLPrinter.NO_CONTENT);
                      } else {
                          generatedXML.writeElement
                              (namespaceAbbrev, namespace,
                               currentProperty.getName(), 
                               WebdavXMLPrinter.OPENING);
                          generatedXML.writeText
                              (currentPropertyValue.toString());
                          generatedXML.writeElement
                              (namespaceAbbrev, namespace,
                               currentProperty.getName(), 
                               WebdavXMLPrinter.CLOSING);
                      }
                  }
              }
              
              generatedXML.writeElement(null, "prop", WebdavXMLPrinter.CLOSING);
              generatedXML.writeProperty(null, "status", status);
              generatedXML.writeElement(null, "propstat", 
                                        WebdavXMLPrinter.CLOSING);
              
  	    break;
  	case FIND_PROPERTY_NAMES :
  	    // Show properties for current object.
              
              status = new String("HTTP/1.1 " + WebdavStatus.SC_OK 
                                  + " " + WebdavStatus.getStatusText
                                  (WebdavStatus.SC_OK));
              
              generatedXML.writeElement(null, "propstat", 
                                        WebdavXMLPrinter.OPENING);
              generatedXML.writeElement(null, "prop", WebdavXMLPrinter.OPENING);
              
              // Lock information
              
              generatedXML.writeElement(null, "lockdiscovery", 
                                        WebdavXMLPrinter.NO_CONTENT);
              generatedXML.writeElement(null, "supportedlock", 
                                        WebdavXMLPrinter.NO_CONTENT);
              
              // Then, add this resource's custom properties
              propertyList = revisionDescriptor.enumerateProperties();
              
              while (propertyList.hasMoreElements()) {
                  NodeProperty currentProperty = 
                      (NodeProperty) propertyList.nextElement();
                  if (currentProperty != null) {
                      String namespace = currentProperty.getNamespace();
                      String namespaceAbbrev = 
                          (String) namespaceAbbrevs.get(namespace);
                      generatedXML.writeElement
                          (namespaceAbbrev, namespace,
                           currentProperty.getName(), 
                           WebdavXMLPrinter.NO_CONTENT);
                  }
              }
              
              generatedXML.writeElement(null, "prop", WebdavXMLPrinter.CLOSING);
              generatedXML.writeProperty(null, "status", status);
              generatedXML.writeElement(null, "propstat", 
                                        WebdavXMLPrinter.CLOSING);
              
  	    break;
  	case FIND_BY_PROPERTY :
  	    // Show requested properties value.
              
              propertyList = propertyVector.elements();
              
              generatedXML.writeElement(null, "propstat", 
                                        WebdavXMLPrinter.OPENING);
              generatedXML.writeElement(null, "prop", WebdavXMLPrinter.OPENING);
              
              status = new String("HTTP/1.1 " + WebdavStatus.SC_OK 
                                  + " " + WebdavStatus.getStatusText
                                  (WebdavStatus.SC_OK));
              
              Vector propertiesNotFoundVector = new Vector();
              
              while (propertyList.hasMoreElements()) {
                  Property property = (Property) propertyList.nextElement();
                  String propertyName = property.name;
                  String propertyNamespace = property.namespace;
                  
                  // Lock information, dynamically generated
                  
                  if ((propertyName.equals("lockdiscovery")) && 
                      (propertyNamespace.equals
                       (NodeProperty.DEFAULT_NAMESPACE))) {
                      // Return list of active locks ...
                      if (objectLockToken != null) {
                          showLockDiscoveryInfo(objectLockToken, generatedXML);
                      }
                  } else if ((propertyName.equals("supportedlock")) && 
                             (propertyNamespace.equals
                              (NodeProperty.DEFAULT_NAMESPACE))) {
                      // Supported locks
                      generatedXML.writeElement(null, "supportedlock", 
                                                WebdavXMLPrinter.OPENING);
                      generatedXML.writeText(SUPPORTED_LOCK);
                      generatedXML.writeElement(null, "supportedlock", 
                                                WebdavXMLPrinter.CLOSING);
                  } else {
                      
                      // Search in the custom properties
                      
                      NodeProperty currentProperty = 
                          revisionDescriptor.getProperty(propertyName,
                                                         propertyNamespace);
                      if (currentProperty != null) {
                          Object currentPropertyValue = 
                              currentProperty.getValue();
                          if ((currentPropertyValue == null) || 
                              (currentPropertyValue.toString().equals(""))) {
                              generatedXML.writeElement
                                  (property.namespaceAbbrev, null,
                                   currentProperty.getName(), 
                                   WebdavXMLPrinter.NO_CONTENT);
                          } else {
                              generatedXML.writeElement
                                  (property.namespaceAbbrev, null,
                                   currentProperty.getName(), 
                                   WebdavXMLPrinter.OPENING);
                              generatedXML.writeText
                                  (currentPropertyValue.toString());
                              generatedXML.writeElement
                                  (property.namespaceAbbrev, null,
                                   currentProperty.getName(), 
                                   WebdavXMLPrinter.CLOSING);
                          }
                      } else {
                          propertiesNotFoundVector.addElement(propertyName);
                      }
                  }
                  
              }
              
              generatedXML.writeElement(null, "prop", WebdavXMLPrinter.CLOSING);
              generatedXML.writeProperty(null, "status", status);
              generatedXML.writeElement(null, "propstat", 
                                        WebdavXMLPrinter.CLOSING);
              
              Enumeration propertiesNotFoundList = 
                  propertiesNotFoundVector.elements();
              
              if (propertiesNotFoundList.hasMoreElements()) {
                  
                  status = new String("HTTP/1.1 " + WebdavStatus.SC_NOT_FOUND 
                                      + " " + WebdavStatus.getStatusText
                                      (WebdavStatus.SC_NOT_FOUND));
                  
                  generatedXML.writeElement(null, "propstat", 
                                            WebdavXMLPrinter.OPENING);
                  generatedXML.writeElement(null, "prop", 
                                            WebdavXMLPrinter.OPENING);
                  
                  while (propertiesNotFoundList.hasMoreElements()) {
                      generatedXML.writeElement
                          (null, (String) propertiesNotFoundList.nextElement(), 
                           WebdavXMLPrinter.NO_CONTENT);
                  }
                  
                  generatedXML.writeElement(null, "prop", 
                                            WebdavXMLPrinter.CLOSING);
                  generatedXML.writeProperty(null, "status", status);
                  generatedXML.writeElement(null, "propstat", 
                                            WebdavXMLPrinter.CLOSING);
                  
              }
              
              break;
          }
          
          generatedXML.writeElement(null, "response", WebdavXMLPrinter.CLOSING);
          
      }
      
      
      /**
       * Parse a node for namespace declaration attributes.
       * 
       * @param node DOM node
       */
      protected void parseNodeNamespaceDeclarations(Node node) {
          
          NamedNodeMap nodeMap = node.getAttributes();
          if (nodeMap != null) {
              for (int i = 0; i < nodeMap.getLength(); i++) {
                  Node currentNode = nodeMap.item(i);
                  if (currentNode.getNodeType() != Node.ATTRIBUTE_NODE)
                      continue;
                  String attributeName = currentNode.getNodeName();
                  if (attributeName.startsWith("xmlns")) {
                      // We found a namespace declaration
                      if (attributeName.equals("xmlns")) {
                          defaultNamespace = currentNode.getNodeValue();
                      } else {
                          // Stripping out the prefix
                          if (attributeName.startsWith("xmlns:")) {
                              String namespaceAbbreviation =
                                  attributeName.substring(6);
                              namespaces.put(namespaceAbbreviation, 
                                             currentNode.getNodeValue());
                              namespaceAbbrevs.put(currentNode.getNodeValue(),
                                                   namespaceAbbreviation);
                          }
                      }
                  }
              }
          }
          
      }
      
      
      // -------------------------------------------------------- Private Methods
      
      
      /**
       * Parse the namespace info of a node name.
       * 
       * @param node The DOM node to parse
       * @return The corresponding Property object
       */
      private Property getProperty(Node node) {
          
          Property property = new Property();
          
          String nodeName = node.getNodeName();
          int colon = nodeName.indexOf(':');
          if (colon != -1) {
              property.name = nodeName.substring(colon + 1);
              property.namespaceAbbrev = nodeName.substring(0, colon - 1);
              String namespace = 
                  (String) namespaces.get(property.namespaceAbbrev);
              if ((namespace) != null) {
                  property.namespace = namespace;
              } else {
                  property.namespace = defaultNamespace;
              }
          } else {
              property.name = nodeName;
              property.namespace = defaultNamespace;
          }
          
          return property;
          
      }
      
      
      /**
       * Generate a namespace abbreviation for the given namespace.
       * 
       * @param namespaceName Name of the namespace
       */
      private void generateNamespaceAbbreviation(String namespaceName) {
          
          if (namespaces.get(namespaceName) != null)
              return;
          
          String namespaceAbbrev = "ns" + namespaceNumber++;
          while (namespaces.get(namespaceAbbrev) != null) {
              namespaceAbbrev = "ns" + namespaceNumber++;
          }
          
          namespaces.put(namespaceAbbrev, namespaceName);
          
      }
      
      
      /**
       * Generate namespace declaration attributes.
       * 
       * @return String namespace attributes
       */
      private String generateNamespaceDeclarations() {
          
          StringBuffer result = new StringBuffer();
          
          result.append(" xmlns=\"").append(defaultNamespace).append("\" ");
          
          Enumeration abbreviationList = namespaces.keys();
          while (abbreviationList.hasMoreElements()) {
              
              String abbrev = (String) abbreviationList.nextElement();
              String namespace = (String) namespaces.get(abbrev);
              result.append("xmlns:").append(abbrev).append("=\"")
                  .append(namespace).append("\" ");
              
          }
          
          return result.toString();
          
      }
      
      
      /**
       * Show lockdiscovery info.
       * 
       * @exception WebdavException Something is wrong with the servlet container
       */
      private void showLockDiscoveryInfo(NodeLock token, 
                                         WebdavXMLPrinter generatedXML) 
          throws WebdavException {
          
          generatedXML.writeElement(null, "lockdiscovery", 
                                    WebdavXMLPrinter.OPENING);
          
          generatedXML.writeElement(null, "activelock", 
                                    WebdavXMLPrinter.OPENING);
          
          generatedXML.writeElement(null, "locktype", WebdavXMLPrinter.OPENING);
          generatedXML.writeElement(null, "write", WebdavXMLPrinter.NO_CONTENT);
          generatedXML.writeElement(null, "locktype", WebdavXMLPrinter.CLOSING);
          
          generatedXML.writeElement(null, "lockscope", WebdavXMLPrinter.OPENING);
          if (token.isExclusive()) {
              generatedXML.writeElement(null, "exclusive", 
                                        WebdavXMLPrinter.NO_CONTENT);
          } else {
              generatedXML.writeElement(null, "shared", 
                                        WebdavXMLPrinter.NO_CONTENT);
          }
          generatedXML.writeElement(null, "lockscope", WebdavXMLPrinter.CLOSING);
          
          generatedXML.writeElement(null, "depth", WebdavXMLPrinter.OPENING);
          if (token.isInheritable()) {
              generatedXML.writeText("Infinity");
          } else {
              generatedXML.writeText("0");
          }
          generatedXML.writeElement(null, "depth", WebdavXMLPrinter.CLOSING);
          
          generatedXML.writeElement(null, "owner", WebdavXMLPrinter.OPENING);
          generatedXML.writeElement(null, "href", WebdavXMLPrinter.OPENING);
          generatedXML.writeText(req.getServletPath() + token.getSubjectUri());
          generatedXML.writeElement(null, "href", WebdavXMLPrinter.CLOSING);
          generatedXML.writeElement(null, "owner", WebdavXMLPrinter.CLOSING);
          
          generatedXML.writeElement(null, "timeout", WebdavXMLPrinter.OPENING);
          generatedXML.writeText("Second-" 
                                 + (new Long((token.getExpirationDate().getTime()
                                              - (new Date()).getTime())/1000))
                                 .toString());
          generatedXML.writeElement(null, "timeout", WebdavXMLPrinter.CLOSING);
          
          generatedXML.writeElement(null, "locktoken", WebdavXMLPrinter.OPENING);
          generatedXML.writeElement(null, "href", WebdavXMLPrinter.OPENING);
          // Put here the token Id
          generatedXML.writeText("opaquelocktoken:" + token.getLockId());
          generatedXML.writeElement(null, "href", WebdavXMLPrinter.CLOSING);
          generatedXML.writeElement(null, "locktoken", WebdavXMLPrinter.CLOSING);
          
          generatedXML.writeElement(null, "activelock", 
                                    WebdavXMLPrinter.CLOSING);
          
          generatedXML.writeElement(null, "lockdiscovery", 
                                    WebdavXMLPrinter.CLOSING);
          
      }
      
      
      // --------------------------------------------------- Property Inner Class
      
      
      private class Property {
          
          public String name;
          public String value;
          public String namespace;
          public String namespaceAbbrev;
          public int status = WebdavStatus.SC_OK;
          
      }
      
      
  }
  
  
  
  1.1                  jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/PropPatchMethod.java
  
  Index: PropPatchMethod.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/PropPatchMethod.java,v 1.1 2000/11/22 06:20:46 remm Exp $
   * $Revision: 1.1 $
   * $Date: 2000/11/22 06:20:46 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */ 
  
  package org.apache.slide.webdav.method;
  
  import java.security.Principal;
  import java.io.*;
  import java.util.*;
  import javax.servlet.*;
  import javax.servlet.http.*;
  import org.w3c.dom.*;
  import org.xml.sax.InputSource;
  import org.apache.slide.authenticate.CredentialsToken;
  import org.apache.slide.common.*;
  import org.apache.slide.util.dom.DOMWriter;
  import org.apache.slide.security.AccessDeniedException;
  import org.apache.slide.webdav.common.*;
  import org.apache.slide.webdav.*;
  import org.apache.slide.structure.*;
  import org.apache.slide.lock.*;
  import org.apache.slide.content.*;
  import javax.xml.parsers.DocumentBuilder;
  
  /**
   * PROPPATCH method.
   * 
   * @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
   */
  public class PropPatchMethod extends WebdavMethod {
      
      
      // -------------------------------------------------------------- Constants
      
      
      private static final int SET = 0;
      private static final int REMOVE = 1;
      
      
      // ----------------------------------------------------- Instance Variables
      
      
      /**
       * Properties to set. Vector of SlideProperty objects.
       */
      private Vector propertiesToSet;
      
      /**
       * Properties to remove. Vector of String.
       */
      private Vector propertiesToRemove;
      
      
      /**
       * DOM Writer.
       */
      private DOMWriter domWriter;
      
      
      /**
       * Resource which will have its properties updated.
       */
      private String resourcePath;
      
      
      // ----------------------------------------------------------- Constructors
      
      
      /**
       * PROPPATCH method constructor.
       * 
       * @param token Namespace access token
       * @param req HTTP request
       * @param resp HTTP response
       */
      public PropPatchMethod(GenericServlet servlet, NamespaceAccessToken token,
                             HttpServletRequest req, HttpServletResponse resp) {
          super(servlet, token, req, resp);
          readRequestContent();
      }
      
      
      // ------------------------------------------------------ Protected Methods
      
      
      /**
       * Parse the request.
       * 
       * @exception WebdavException Bad request
       */
      protected void parseRequest() 
          throws WebdavException {
          
          resourcePath = requestUri;
          if (resourcePath == null) {
              resourcePath = "/";
          }
          
          propertiesToSet = new Vector();
          
          propertiesToRemove = new Vector();
          
          if (requestBody.length != 0) {
              try {
                  Node setNode = null;
                  Node removeNode = null;
                  
                  Document document = documentBuilder.parse(new InputSource(
                      (new StringReader(new String(requestBody)))));
                  
                  // Get the root element of the document
                  Element rootElement = document.getDocumentElement();
                  NodeList childList = rootElement.getChildNodes();
                  
                  parseNodeNamespaceDeclarations(rootElement);
                  
                  for (int i=0; i < childList.getLength(); i++) {
                      Node currentNode = childList.item(i);
                      switch (currentNode.getNodeType()) {
                      case Node.TEXT_NODE:
                          break;
                      case Node.ELEMENT_NODE:
                          parseNodeNamespaceDeclarations(currentNode);
                          if (currentNode.getNodeName().endsWith("set")) {
                              NodeList tempList = currentNode.getChildNodes();
                              for (int j=0; j < tempList.getLength(); j++) {
                                  switch (tempList.item(j).getNodeType()) {
                                  case Node.TEXT_NODE:
                                      break;
                                  case Node.ELEMENT_NODE:
                                      parseNodeNamespaceDeclarations
                                          (tempList.item(j));
                                      if (tempList.item(j).getNodeName()
                                          .endsWith("prop")) {
                                          parseSetNode(tempList.item(j));
                                      }
                                      break;
                                  }
                              }
                          }
                          if (currentNode.getNodeName().endsWith("remove")) {
                              NodeList tempList = currentNode.getChildNodes();
                              for (int j=0; j < tempList.getLength(); j++) {
                                  switch (tempList.item(j).getNodeType()) {
                                  case Node.TEXT_NODE:
                                      break;
                                  case Node.ELEMENT_NODE:
                                      parseNodeNamespaceDeclarations
                                          (tempList.item(j));
                                      if (tempList.item(j).getNodeName()
                                          .endsWith("prop")) {
                                          parseRemoveNode(tempList.item(j));
                                      }
                                      break;
                                  }
                              }
                          }
                          break;
                      }
                  }
                  
              } catch(Exception e) {
                  e.printStackTrace();
                  resp.setStatus(WebdavStatus.SC_BAD_REQUEST);
                  throw new WebdavException(WebdavStatus.SC_BAD_REQUEST);
              }
          } else {
              try {
                  resp.sendError(WebdavStatus.SC_BAD_REQUEST, 
                                  WebdavStatus.getStatusText
                                 (WebdavStatus.SC_BAD_REQUEST));
              } catch (IOException e) {
                  e.printStackTrace();
              }
          }
          
      }
      
      
      /**
       * Execute the request.
       * 
       * @exception WebdavException 
       */
      protected void executeRequest() 
          throws WebdavException {
          
          try {
              
              NodeRevisionDescriptors revisionDescriptors = 
                  content.retrieve(credToken, resourcePath);
              NodeRevisionDescriptor revisionDescriptor = null;
              
              try {
                  revisionDescriptor = 
                      content.retrieve(credToken, revisionDescriptors);
              } catch (RevisionDescriptorNotFoundException ex) {
                  revisionDescriptor = new NodeRevisionDescriptor(0);
                  // TODO : Create the initial revision ?
              }
              
              // Modifying the properties
              
              Enumeration propertyList = null;
              
              propertyList = propertiesToSet.elements();
              
              while (propertyList.hasMoreElements()) {
                  
                  Property currentProperty = 
                      (Property) propertyList.nextElement();
                  
                  if (checkProperty(currentProperty, SET)) {
                      
                      NodeProperty newProperty = 
                          new NodeProperty(currentProperty.name,
                                           currentProperty.value,
                                           currentProperty.namespace);
                      revisionDescriptor.setProperty(newProperty);
                      
                  }
              }
              
              propertyList = propertiesToRemove.elements();
              
              while (propertyList.hasMoreElements()) {
                  
                  Property currentProperty = 
                      (Property) propertyList.nextElement();
                  
                  if (checkProperty(currentProperty, REMOVE)) {
                      
                      revisionDescriptor.removeProperty(currentProperty.name);
                      
                  }
                  
              }
              
              // TEMP !!!! We should do a store instead !!
              content.create(credToken, resourcePath, revisionDescriptor, null);
              
          } catch(RevisionAlreadyExistException e) {
  	    // 500 - Internal server error
              System.out.println(e.getMessage());
              resp.setStatus(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
  	    throw new WebdavException(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
          } catch (LinkedObjectNotFoundException e) {
              // 404 - Not found
              System.out.println(e.getMessage());
              resp.setStatus(WebdavStatus.SC_NOT_FOUND);
  	} catch (ObjectNotFoundException e) {
              // 404 - Not found
              System.out.println(e.getMessage());
              resp.setStatus(WebdavStatus.SC_NOT_FOUND);
          } catch (AccessDeniedException e) {
              // 403 - Forbidden
              System.out.println(e.getMessage());
              resp.setStatus(WebdavStatus.SC_FORBIDDEN);
  	} catch (ObjectLockedException e) {
              // Locked
              System.out.println(e.getMessage());
              resp.setStatus(WebdavStatus.SC_LOCKED);
          } catch (ServiceAccessException e) {
  	    // 500 - Internal server error
              System.out.println(e.getMessage());
              resp.setStatus(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
  	    throw new WebdavException(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
  	} catch (RuntimeException e) {
  	    // 500 - Internal server error
              e.printStackTrace();
              resp.setStatus(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
  	    throw new WebdavException(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
  	}
          
          // No serious errors. Printing the XML report.
          resp.setStatus(WebdavStatus.SC_MULTI_STATUS);
          writeReport();
          
      }
      
      
      // -------------------------------------------------------- Private Methods
      
      
      /**
       * Parse the set property node given.
       */
      private void parseSetNode(Node setNode) {
          
          NodeList childList = setNode.getChildNodes();
          
          for (int i=0; i < childList.getLength(); i++) {
              Node currentNode = childList.item(i);
              switch (currentNode.getNodeType()) {
              case Node.TEXT_NODE:
                  break;
              case Node.ELEMENT_NODE:
                  
                  parseNodeNamespaceDeclarations(currentNode);
                  
                  Property propertyToSet = getProperty(currentNode);
                  
                  StringWriter writer = new StringWriter();
                  domWriter = new DOMWriter(writer, true);
                  
                  // Printing all child nodes using the DOM printer
                  NodeList childNodes = currentNode.getChildNodes();
                  Node childNode = childNodes.item(0);
                  int pos = 0;
                  while (childNode != null) {
                      domWriter.print(childNode);
                      childNode = childNodes.item(++pos);
                  }
                  
                  String nodeValue = writer.toString();
                  propertyToSet.value = nodeValue;
                  
                  propertiesToSet.addElement(propertyToSet);
                  
                  break;
              }
          }
      }
      
      
      /**
       * Parse the remove property node given.
       */
      private void parseRemoveNode(Node removeNode) {
          
          NodeList childList = removeNode.getChildNodes();
          
          for (int i=0; i < childList.getLength(); i++) {
              Node currentNode = childList.item(i);
              switch (currentNode.getNodeType()) {
              case Node.TEXT_NODE:
                  break;
              case Node.ELEMENT_NODE:
                  
                  parseNodeNamespaceDeclarations(currentNode);
                  
                  Property propertyToRemove = getProperty(currentNode);
                  
                  propertiesToRemove.addElement(propertyToRemove);
                  
                  break;
              }
          }
      }
      
      
      /**
       * Parse the namespace info of a node name.
       * 
       * @param node The DOM node to parse
       * @return The corresponding Property object
       */
      private Property getProperty(Node node) {
          
          Property property = new Property();
          
          String nodeName = node.getNodeName();
          int colon = nodeName.indexOf(':');
          if (colon != -1) {
              property.name = nodeName.substring(colon + 1);
              property.namespaceAbbrev = nodeName.substring(0, colon - 1);
              String namespace = 
                  (String) namespaces.get(property.namespaceAbbrev);
              if ((namespace) != null) {
                  property.namespace = namespace;
              } else {
                  property.namespace = defaultNamespace;
              }
          } else {
              property.name = nodeName;
              property.namespace = defaultNamespace;
          }
          
          return property;
          
      }
      
      
      /**
       * Check if the property is a live property which should have its value
       * enforced by the server.
       * 
       * @param property The property object
       * @param actionType Can be either SET or REMOVE
       */
      private boolean checkProperty(Property property, int actionType) {
          
          // Checking the standard DAV properties which can't be modified using 
          // a propatch.
          if (
              (property.name.equalsIgnoreCase("creationdate")) ||
              (property.name.equalsIgnoreCase("getcontentlength")) ||
              (property.name.equalsIgnoreCase("getetag")) ||
              (property.name.equalsIgnoreCase("getlastmodified")) ||
              (property.name.equalsIgnoreCase("lockdiscovery"))
              ) {
              property.status = WebdavStatus.SC_CONFLICT;
              return false;
          }
          
          switch (actionType) {
              
          case SET:
              
              break;
              
          case REMOVE:
              
              break;
              
          }
          
          return true;
          
      }
      
      
      /**
       * Write the report.
       */
      private void writeReport() 
          throws WebdavException {
          
          // Create multistatus object
          WebdavXMLPrinter generatedXML = new WebdavXMLPrinter();
          
          generatedXML.writeXMLHeader();
          generatedXML.writeElement("d", "DAV", "multistatus", 
                                    WebdavXMLPrinter.OPENING);
          
          generatedXML.writeElement("d", null, "response", 
                                    WebdavXMLPrinter.OPENING);
          generatedXML.writeProperty("d", null, "href", requestUri);
          
          
          
          // Parse the two properties list, and printout their status
          Enumeration propertyList = null;
          
          propertyList = propertiesToSet.elements();
          
          while(propertyList.hasMoreElements()) {
              Property property = (Property) propertyList.nextElement();
              generatedXML.writeElement("d", null, "propstat", 
                                        WebdavXMLPrinter.OPENING);
              generatedXML.writeElement("d", null, "prop", 
                                        WebdavXMLPrinter.OPENING);
              generatedXML.writeElement(property.namespaceAbbrev, 
                                        property.namespace, property.name,
                                        WebdavXMLPrinter.NO_CONTENT);
              generatedXML.writeElement("d", null, "prop", 
                                        WebdavXMLPrinter.CLOSING);
              generatedXML.writeProperty
                  ("d", null, "status", "HTTP/1.1 " + property.status + " " 
                   + WebdavStatus.getStatusText(property.status));
              generatedXML.writeElement("d", null, "propstat", 
                                        WebdavXMLPrinter.CLOSING);
          }
          
          propertyList = propertiesToRemove.elements();
          
          while(propertyList.hasMoreElements()) {
              Property property = (Property) propertyList.nextElement();
              generatedXML.writeElement("d", null, "propstat", 
                                        WebdavXMLPrinter.OPENING);
              generatedXML.writeElement("d", null, "prop", 
                                        WebdavXMLPrinter.OPENING);
              generatedXML.writeElement(property.namespaceAbbrev, 
                                        property.namespace, property.name,
                                        WebdavXMLPrinter.NO_CONTENT);
              generatedXML.writeElement("d", null, "prop", 
                                        WebdavXMLPrinter.CLOSING);
              generatedXML.writeProperty
                  ("d", null, "status", "HTTP/1.1 " + property.status + " " 
                   + WebdavStatus.getStatusText(property.status));
              generatedXML.writeElement("d", null, "propstat", 
                                        WebdavXMLPrinter.CLOSING);
          }
          
          generatedXML.writeElement("d", null, "response", 
                                    WebdavXMLPrinter.CLOSING);
          generatedXML.writeElement("d", "multistatus", 
                                    WebdavXMLPrinter.CLOSING);
          
  	try {
              Writer writer = resp.getWriter();
              writer.write(generatedXML.toString());
  	    writer.flush();
  	} catch (Exception e) {
              e.printStackTrace();
  	    throw new WebdavException(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
  	}
          
      }
      
      
      // --------------------------------------------------- Property Inner Class
      
      
      private class Property {
          
          public String name;
          public String value;
          public String namespace;
          public String namespaceAbbrev;
          public int status = WebdavStatus.SC_OK;
          
      }
      
      
  }
  
  
  
  1.1                  jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/PutMethod.java
  
  Index: PutMethod.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/PutMethod.java,v 1.1 2000/11/22 06:20:46 remm Exp $
   * $Revision: 1.1 $
   * $Date: 2000/11/22 06:20:46 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */ 
  
  package org.apache.slide.webdav.method;
  
  import java.security.Principal;
  import java.io.*;
  import java.util.*;
  import java.text.DateFormat;
  import java.text.SimpleDateFormat;
  import javax.servlet.*;
  import javax.servlet.http.*;
  import org.apache.slide.common.*;
  import org.apache.slide.structure.*;
  import org.apache.slide.content.*;
  import org.apache.slide.security.*;
  import org.apache.slide.lock.*;
  import org.apache.slide.webdav.common.*;
  import org.apache.slide.webdav.*;
  
  /**
   * PUT method.
   * 
   * @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
   */
  public class PutMethod extends WebdavMethod {
      
      
      // -------------------------------------------------------------- Constants
      
      
      /**
       * HTTP Date format pattern (RFC 2068, 822, 1123).
       */
      public static final String DATE_FORMAT = "EEE, d MMM yyyy kk:mm:ss z";
      
      
      // ----------------------------------------------------- Instance Variables
      
      
      /**
       * Resource to be written.
       */
      private String resourcePath;
      
      
      // ----------------------------------------------------------- Constructors
      
      
      /**
       * PUT Method constructor.
       * 
       * @param token Namespace access token
       * @param req HTTP request
       * @param resp HTTP response
       */
      public PutMethod(GenericServlet servlet, NamespaceAccessToken token, 
                       HttpServletRequest req, HttpServletResponse resp) {
          super(servlet, token, req, resp);
      }
      
      
      // ------------------------------------------------------ Protected Methods
      
      
      /**
       * Parse XML request.
       * 
       * @exception WebdavException Does not happen
       */
      protected void parseRequest() 
  	throws WebdavException {
          resourcePath = requestUri;
          if (resourcePath == null) {
              resourcePath = "/";
          }
      }
      
      /**
       * Execute request.
       * 
       * @exception WebdavException Bad request
       */
      protected void executeRequest() 
  	throws WebdavException {
          
          try {
              
              try {
                  
                  NodeRevisionDescriptors revisionDescriptors = 
                      content.retrieve(credToken, resourcePath);
                  NodeRevisionNumber revisionNumber = 
                      revisionDescriptors.getLatestRevision();
                  NodeRevisionDescriptor revisionDescriptor = 
                      new NodeRevisionDescriptor(req.getContentLength());
                  NodeRevisionContent revisionContent = 
                      new NodeRevisionContent();
                  //revisionContent.setContent(req.getReader());
                  revisionContent.setContent(req.getInputStream());
                  
                  NodeProperty property = null;
                  
                  // Get content length
                  property = new NodeProperty
                      ("getcontentlength", new Long(req.getContentLength()),
                       true);
                  revisionDescriptor.setProperty(property);
                  
                  // Last modification date
                  DateFormat formatter = new SimpleDateFormat(DATE_FORMAT);
                  property = new NodeProperty("getlastmodified", 
                                              new Date(), 
                                              true);
                  revisionDescriptor.setProperty(property);
                  
                  // Etag generation
                  String etag = resourcePath.hashCode() + "_" 
                      + revisionNumber.hashCode() + "_"
                      + revisionDescriptor.getContentLength();
                  property = new NodeProperty("getetag", etag, true);
                  revisionDescriptor.setProperty(property);
                  
                  // Resource type
                  property = new NodeProperty("resourcetype", "", true);
                  revisionDescriptor.setProperty(property);
                  
                  content.create(credToken, resourcePath, revisionDescriptor, 
                                 revisionContent);
                  
              } catch (LinkedObjectNotFoundException e) {
                  // Nothing we can do here ...
                  e.printStackTrace();
              } catch (ObjectNotFoundException e) {
                  
                  // Todo : Check to see if parent exists
                  SubjectNode subject = new SubjectNode();
                  // Creating an object
                  structure.create(credToken, subject, resourcePath);
                  
                  NodeRevisionDescriptor revisionDescriptor = 
                      new NodeRevisionDescriptor(req.getContentLength());
                  
                  NodeProperty property = null;
                  
                  // Creation date
                  DateFormat formatter = new SimpleDateFormat(DATE_FORMAT);
                  property = new NodeProperty("creationdate", 
                                              new Date(), 
                                              true);
                  revisionDescriptor.setProperty(property);
                  
                  // Display name
                  property = new NodeProperty("displayname", resourcePath, true);
                  revisionDescriptor.setProperty(property);
                  
                  // Resource type
                  property = new NodeProperty("resourcetype", "", true);
                  revisionDescriptor.setProperty(property);
                  
                  // Source
                  property = new NodeProperty("source", "", true);
                  revisionDescriptor.setProperty(property);
                  
                  // Get content language
                  property = new NodeProperty("getcontentlanguage", "en", true);
                  revisionDescriptor.setProperty(property);
                  
                  // Get content length
                  property = new NodeProperty
                      ("getcontentlength", 
                       new Long(req.getContentLength()), true);
                  revisionDescriptor.setProperty(property);
                  
                  // Get content type
                  String contentType = 
                      servlet.getServletContext().getMimeType(resourcePath);
                  if (contentType == null) {
                      contentType = "TEXT/PLAIN";
                  }
                  property = new NodeProperty("getcontenttype", contentType, 
                                              true);
                  revisionDescriptor.setProperty(property);
                  
                  // Last modification date
                  property = new NodeProperty
                      ("getlastmodified", new Date(), true);
                  revisionDescriptor.setProperty(property);
                  
                  // Etag generation
                  String etag = resourcePath.hashCode() + "_" 
                      + (new NodeRevisionNumber()).hashCode() + "_"
                      + req.getContentLength();
                  property = new NodeProperty("getetag", etag, true);
                  revisionDescriptor.setProperty(property);
                  
                  if (isMsProprietarySupport()) {
                      
                      // Name
                      /*
                        property = new NodeProperty("name", resourcePath, 
                        "d", "DAV");
                        revisionDescriptor.setProperty(property);
                      */
                      
                      // ParentName
                      // TODO : Fix this
                      /*
                        property = new NodeProperty("parentname", resourcePath, 
                        "ms", "MICROSOFT");
                        revisionDescriptor.setProperty(property);
                      */
                      
                      // Href
                      /*
                        property = new NodeProperty("href", resourcePath, 
                        "ms", "MICROSOFT");
                        revisionDescriptor.setProperty(property);
                      */
                      
                      // Is hidden
                      property = new NodeProperty("ishidden", "0", "MICROSOFT");
                      revisionDescriptor.setProperty(property);
                      
                      // Is collection
                      property = new NodeProperty("iscollection", "0", 
                                                  "MICROSOFT");
                      revisionDescriptor.setProperty(property);
                      
                      // Is read only
                      property = new NodeProperty("isreadonly", "0", 
                                                  "MICROSOFT");
                      revisionDescriptor.setProperty(property);
                      
                      // Content class
                      // TODO : Find what it is ...
                      /*
                        property = new NodeProperty("contentclass", "", 
                        "MICROSOFT");
                        revisionDescriptor.setProperty(property);
                      */
                      
                      // Last accessed
                      property = new NodeProperty("lastaccessed", 
                                                  (new Date()).toString(), 
                                                  "MICROSOFT");
                      revisionDescriptor.setProperty(property);
                      
                      // Is structured document
                      /*
                        property = new NodeProperty("isstructureddocument", 
                        "false", "MICROSOFT");
                        revisionDescriptor.setProperty(property);
                      */
                      
                      // Default document
                      /*
                        property = new NodeProperty("defaultdocument", 
                        "", "MICROSOFT");
                        revisionDescriptor.setProperty(property);
                      */
                      
                      // Is root
                      /*
                        property = new NodeProperty("isroot", "false", 
                        "MICROSOFT");
                        revisionDescriptor.setProperty(property);
                      */
                      
                  }
                  
                  // Creating revisionDescriptor associated with the object
                  NodeRevisionContent revisionContent = 
                      new NodeRevisionContent();
                  revisionContent.setContent(req.getInputStream());
                  
                  content.create(credToken, resourcePath, revisionDescriptor, 
                                 revisionContent);
                  
              }
              
              String status = new String("HTTP/1.1 " + WebdavStatus.SC_CREATED 
                                         + " " + WebdavStatus.getStatusText
                                         (WebdavStatus.SC_CREATED));;
              
              
          } catch (RevisionAlreadyExistException e) {
              // 404 - Not found
              System.out.println(e.getMessage());
              resp.setStatus(WebdavStatus.SC_NOT_FOUND);
              /*
                } catch (RevisionDescriptorNotFoundException e) {
                // 404 - Not found
                System.out.println(e.getMessage());
                resp.setStatus(WebdavStatus.SC_NOT_FOUND);
              */
  	} catch (ObjectAlreadyExistsException e) {
              // 404 - Not found
              System.out.println(e.getMessage());
              resp.setStatus(WebdavStatus.SC_NOT_FOUND);
  	} catch (ObjectNotFoundException e) {
              // 409 - Conflict
              resp.setStatus(WebdavStatus.SC_CONFLICT);
  	} catch (LinkedObjectNotFoundException e) {
              // 404 - Not found
              System.out.println(e.getMessage());
              resp.setStatus(WebdavStatus.SC_NOT_FOUND);
  	} catch (AccessDeniedException e) {
              // 403 - Forbidden
              System.out.println(e.getMessage());
              resp.setStatus(WebdavStatus.SC_FORBIDDEN);
  	} catch (ObjectLockedException e) {
              // Locked
              System.out.println(e.getMessage());
              resp.setStatus(WebdavStatus.SC_LOCKED);
          } catch (ServiceAccessException e) {
  	    // 500 - Internal server error
              System.out.println(e.getMessage());
              resp.setStatus(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
  	    throw new WebdavException(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
  	} catch (IOException e) {
  	    // 500 - Internal server error
              e.printStackTrace();
              resp.setStatus(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
  	    throw new WebdavException(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
  	} catch (RuntimeException e) {
  	    // 500 - Internal server error
              e.printStackTrace();
              resp.setStatus(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
  	    throw new WebdavException(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
  	}
          
          
      }
  
  }
  
  
  
  1.1                  jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/UnlockMethod.java
  
  Index: UnlockMethod.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/UnlockMethod.java,v 1.1 2000/11/22 06:20:47 remm Exp $
   * $Revision: 1.1 $
   * $Date: 2000/11/22 06:20:47 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */ 
  
  package org.apache.slide.webdav.method;
  
  import java.security.Principal;
  import java.io.*;
  import java.util.*;
  import javax.servlet.*;
  import javax.servlet.http.*;
  import org.apache.slide.common.*;
  import org.apache.slide.webdav.common.*;
  import org.apache.slide.webdav.*;
  import org.apache.slide.macro.*;
  import org.apache.slide.lock.*;
  import org.apache.slide.content.*;
  import org.apache.slide.security.AccessDeniedException;
  import org.apache.slide.structure.*;
  
  /**
   * UNLOCK method.
   * 
   * @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
   */
  public class UnlockMethod extends WebdavMethod {
      
      
      // ----------------------------------------------------- Instance Variables
      
      
      /**
       * Resource to unlock.
       */
      private String toUnlock;
      
      /**
       * Id.
       */
      private String lockId;
      
      
      // ----------------------------------------------------------- Constructors
      
      
      /**
       * UNLOCK method constructor.
       * 
       * @param token Namespace access token
       * @param req HTTP request
       * @param resp HTTP response
       */
      public UnlockMethod(GenericServlet servlet, NamespaceAccessToken token, 
                          HttpServletRequest req, HttpServletResponse resp) {
  	super(servlet, token, req, resp);
      }
      
      
      // ------------------------------------------------------ Protected Methods
      
      
      /**
       * Parse the request.
       * 
       * @exception WebdavException Bad request
       */
      protected void parseRequest() 
  	throws WebdavException {
          
          // Loads the associated object from the store.
  	toUnlock = requestUri;
  	if (toUnlock == null) {
  	    toUnlock = "/";
  	}
          
          String lockTokenHeader = req.getHeader("Lock-Token");
          if (lockTokenHeader != null) {
              lockId = parseLockToken(lockTokenHeader);
          } else {
              // TODO : The call to UNLOCK is invalid
              System.out.println("Invalid call");
          }
          
      }
      
      
      /**
       * Execute the request.
       * 
       * @exception WebdavException 
       */
      protected void executeRequest() 
          throws WebdavException {
          
          if (lockId != null) {
              
              try {
                  
                  lock.unlock(credToken, requestUri, lockId);
                  
                  // Checking if the resource at the URI isn't a lock-null
                  // resource, in which case we must attempt to delete it
                  ObjectNode node = structure.retrieve(credToken, requestUri);
                  NodeRevisionDescriptors revisionDescriptors = 
                      content.retrieve(credToken, requestUri);
                  NodeRevisionDescriptor revisionDescriptor = 
                      content.retrieve(credToken, revisionDescriptors);
                  NodeProperty typeProperty = 
                      revisionDescriptor.getProperty
                      (NodeRevisionDescriptor.TYPE);
                  
                  if (typeProperty.getValue().toString()
                      .equals("<lock-null/>")) {
                      
                      content.remove(credToken, requestUri, revisionDescriptor);
                      content.remove(credToken, revisionDescriptors);
                      structure.remove(credToken, node);
                      
                  }
                  
                  resp.setStatus(WebdavStatus.SC_NO_CONTENT);
                  
              } catch (SlideException e) {
                  e.printStackTrace();
                  resp.setStatus(WebdavStatus.SC_INTERNAL_SERVER_ERROR);
              }
              
          }
          
      }
      
      
  }
  
  
  
  1.1                  jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/WebdavMethod.java
  
  Index: WebdavMethod.java
  ===================================================================
  /*
   * $Header: /home/cvs/jakarta-slide/src/webdav/server/org/apache/slide/webdav/method/WebdavMethod.java,v 1.1 2000/11/22 06:20:47 remm Exp $
   * $Revision: 1.1 $
   * $Date: 2000/11/22 06:20:47 $
   *
   * ====================================================================
   *
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 1999 The Apache Software Foundation.  All rights 
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer. 
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:  
   *       "This product includes software developed by the 
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Tomcat", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written 
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   *
   * [Additional notices, if required by prior licensing conditions]
   *
   */ 
  
  package org.apache.slide.webdav.method;
  
  import java.security.Principal;
  import java.security.MessageDigest;
  import java.security.NoSuchAlgorithmException;
  import java.io.*;
  import java.util.*;
  import javax.servlet.*;
  import javax.servlet.http.*;
  import javax.xml.parsers.DocumentBuilderFactory;
  import javax.xml.parsers.DocumentBuilder;
  import javax.xml.parsers.ParserConfigurationException;
  import org.w3c.dom.*;
  import org.apache.slide.common.*;
  import org.apache.slide.authenticate.*;
  import org.apache.slide.structure.*;
  import org.apache.slide.content.*;
  import org.apache.slide.lock.*;
  import org.apache.slide.macro.*;
  import org.apache.slide.security.*;
  import org.apache.slide.webdav.common.*;
  import org.apache.slide.webdav.*;
  import org.apache.slide.util.MD5Encoder;
  
  /**
   * WebDAV method.
   * 
   * @author <a href="mailto:remm@apache.org">Remy Maucherat</a>
   */
  public abstract class WebdavMethod {
      
      
      // -------------------------------------------------------------- Constants
      
      
      public static final String LOCK_TOKEN = "opaquelocktoken:";
      
      
      // ----------------------------------------------------- Instance Variables
      
      
      /**
       * Requested Uri.
       */
      protected String requestUri;
      
      
      /**
       * Principal.
       */
      protected Principal principal;
      
      
      /**
       * Servlet request.
       */
      protected HttpServletRequest req;
      
      
      /**
       * Servlet response.
       */
      protected HttpServletResponse resp;
      
      
      /**
       * HTTP servlet.
       */
      protected GenericServlet servlet;
      
      
      /**
       * Servlet context.
       */
      protected ServletContext context;
      
      /**
       * Request body.
       */
      protected char[] requestBody;
      
      
      /**
       * Namespace access token.
       */
      protected NamespaceAccessToken token;
      
      
      /**
       * Files path.
       */
      protected String filesPath;
      
      
      /**
       * Structure helper.
       */
      protected Structure structure;
      
      
      /**
       * Content helper.
       */
      protected Content content;
      
      
      /**
       * Security helper.
       */
      protected Security security;
      
      
      /**
       * Lock helper.
       */
      protected Lock lock;
      
      
      /**
       * Macro helper.
       */
      protected Macro macro;
      
      
      /**
       * Credentials token associated with the principal.
       */
      protected CredentialsToken credToken;
      
      
      /**
       * DOM XML parser.
       */
      protected static DocumentBuilder documentBuilder;
      
      
      /**
       * Namespaces list. Keyed by abbreviation.
       */
      protected Hashtable namespaces;
      
      
      /**
       * Default namespace.
       */
      protected String defaultNamespace = NodeProperty.DEFAULT_NAMESPACE;
      
      
      /**
       * MD5 message digest provider.
       */
      protected static MessageDigest md5Helper;
  
  
      /**
       * The MD5 helper object for this class.
       */
      protected static final MD5Encoder md5Encoder = new MD5Encoder();
      
      
      /**
       * Manager servlet path.
       */
      protected static String managerServletPath = "/manager/";
      
      
      // ----------------------------------------------------------- Constructors
      
      
      /**
       * Method constructor.
       */
      public WebdavMethod(GenericServlet servlet, NamespaceAccessToken token, 
                          HttpServletRequest req, HttpServletResponse resp) {
          
          if (documentBuilder == null) {
              try {
                  documentBuilder = 
                      DocumentBuilderFactory.newInstance().newDocumentBuilder();
              } catch(ParserConfigurationException e) {
                  e.printStackTrace();
              }
          }
          
          this.principal = req.getUserPrincipal();
          this.req = req;
          this.resp = resp;
          this.servlet = servlet;
          this.context = servlet.getServletContext();
          
          this.token = token;
          this.structure = token.getStructureHelper();
          this.content = token.getContentHelper();
          this.security = token.getSecurityHelper();
          this.lock = token.getLockHelper();
          this.macro = token.getMacroHelper();
          if (principal != null) {
              this.credToken = new CredentialsToken(principal);
          } else {
              this.credToken = new CredentialsToken("");
          }
          
          this.credToken.setEnforceLockTokens(true);
          
          this.requestUri = getRelativePath(req);
          
          parseHeaders();
          
          System.out.println(System.currentTimeMillis() + " - " 
                             + req.getMethod() + " on object " + requestUri);
          
      }
      
      
      // --------------------------------------------------------- Public Methods
      
      
      /**
       * Initializes static fields.
       * 
       * @param servletPath Path of the manager servlet
       */
      public static void init(String servletPath) {
          
          // Load the MD5 helper used to calculate signatures.
          try {
              md5Helper = MessageDigest.getInstance("MD5");
          } catch (NoSuchAlgorithmException e) {
              e.printStackTrace();
              throw new IllegalStateException();
          }
          
          if (servletPath != null) {
              managerServletPath = servletPath;
          }
          
      }
      
      
      /**
       * Exceute method.
       * 
       * @exception WebdavException 
       */
      public void run()
          throws WebdavException {
          parseRequest();
          executeRequest();
          
          /*
            if (isMsProprietarySupport()) {
            resp.setHeader("Server", "Microsoft-IIS/5.0");
            }
          */
          
      }
      
      
      // ------------------------------------------------------ Protected Methods
      
      
      /**
       * Return the relative path associated with this servlet.
       *
       * @param request The servlet request we are processing
       */
      protected String getRelativePath(HttpServletRequest request) {
          
          String result = request.getPathInfo();
          if (result == null) {
              result = request.getServletPath();
          }
          if ((result == null) || (result.equals(""))) {
              result = "/";
          }
          return result;
          
      }
      
      
      /**
       * Parse a node for namespace declaration attributes.
       * 
       * @param node DOM node
       */
      protected void parseNodeNamespaceDeclarations(Node node) {
          
          NamedNodeMap nodeMap = node.getAttributes();
          if (nodeMap != null) {
              for (int i = 0; i < nodeMap.getLength(); i++) {
                  Node currentNode = nodeMap.item(i);
                  if (currentNode.getNodeType() != Node.ATTRIBUTE_NODE)
                      continue;
                  String attributeName = currentNode.getNodeName();
                  if (attributeName.startsWith("xmlns")) {
                      // We found a namespace declaration
                      if (attributeName.equals("xmlns")) {
                          defaultNamespace = currentNode.getNodeValue();
                      } else {
                          // Stripping out the prefix
                          if (attributeName.startsWith("xmlns:")) {
                              String namespaceAbbreviation =
                                  attributeName.substring(6);
                              namespaces.put(namespaceAbbreviation, 
                                             currentNode.getNodeValue());
                          }
                      }
                  }
              }
          }
          
      }
      
      
      /**
       * Read request contents.
       * 
       * @param req Request object handed out by the servlet container
       * @return char[] Array of char which contains the body of the request
       */
      protected void readRequestContent() {
          
          namespaces = new Hashtable();
          
          if (req.getContentLength() == 0)
              return;
          
          // TODO : Modify this and make it chunking aware
          
          int contentLength = req.getContentLength();
          
          char[] result = null;
          
          if (contentLength > 0) {
              try {
                  BufferedReader reader = null;
                  requestBody = new char[contentLength];
                  int position = 0;
                  reader = req.getReader();
                  while (position < contentLength) {
                      int nChar = reader.read(requestBody, position, 
                                              contentLength - position);
                      position = position + nChar;
                  }
                  reader.close();
              } catch (IOException e) {
                  System.out.println(e.getMessage());
              } catch (RuntimeException e) {
                  e.printStackTrace();
              }
          }
          
      }
      
      
      /**
       * Parse lock token headers.
       */
      protected void parseHeaders() {
          
          // Retrieve if header
          String ifHeader = req.getHeader("If");
          //System.out.println("If header : " + ifHeader);
          
          if (ifHeader == null)
              return;
          
          // Parse if header and extract the lock tokens
          int pos = ifHeader.indexOf(LOCK_TOKEN);
          int endPos = -1;
          int offset = LOCK_TOKEN.length();
          String lockToken = null;
          
          while (pos != -1) {
              
              endPos = ifHeader.indexOf('>', pos + offset);
              if (endPos == -1) {
                  lockToken = ifHeader;
              } else {
                  lockToken = ifHeader.substring(pos + offset, endPos);
              }
              
              //System.out.println("Lock Token found :-" + lockToken + "-");
              credToken.addLockToken(lockToken);
              
              pos = ifHeader.indexOf(LOCK_TOKEN, endPos);
              
          }
          
      }
      
      
      /**
       * Returns the lock token value from the lock token header.
       * 
       * @return String Opaque lock token value
       */
      protected String parseLockToken(String lockTokenValue) {
          int semi = lockTokenValue.indexOf(":");
          String result = null;
          try {
              result = lockTokenValue.substring(semi + 1, 
                                                lockTokenValue.length() - 1);
          } catch (Exception e) {
              e.printStackTrace();
          }
          return result;
      }
      
      
      /**
       * Tests if a resource is a collection.
       */
      protected boolean isCollection(NodeRevisionDescriptor revisionDescriptor) {
          
          boolean result = false;
          
          if (revisionDescriptor == null)
              return true;
          
          NodeProperty property = revisionDescriptor.getProperty("resourcetype");
          
          if ((property != null) 
              && (property.getValue().equals("<collection/>"))) {
              result = true;
          }
          
          return result;
          
      }
      /**
       * Parse WebDAV XML query.
       * 
       * @exception WebdavException 
       */
      protected abstract void parseRequest() 
          throws WebdavException;
      
      
      /**
       * Generate XML response.
       * 
       * @exception WebdavException 
       */
      protected abstract void executeRequest() 
          throws WebdavException;
      
      
      /**
       * Simulate MS IIS5 ?
       * 
       * @return boolean
       */
      protected boolean isMsProprietarySupport() {
          return (token.getNamespaceConfig().getParameter("ms") != null);
      }
      
      
  }