Package org.apache.webdav.lib

Source Code of org.apache.webdav.lib.WebdavResource

/*
* $Header: /home/cvs/jakarta-slide/src/webdav/client/src/org/apache/webdav/lib/WebdavResource.java,v 1.28 2001/09/02 02:39:24 remm Exp $
* $Revision: 1.28 $
* $Date: 2001/09/02 02:39:24 $
*
* ====================================================================
*
* 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.webdav.lib;

import java.io.File;
import java.io.InputStream;
import java.io.IOException;
import java.io.FileOutputStream;
import java.util.Date;
import java.util.TimeZone;
import java.util.Locale;
import java.util.Vector;
import java.util.Hashtable;
import java.util.Enumeration;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.net.URL;
import java.net.MalformedURLException;

import org.apache.util.WebdavStatus;
import org.apache.util.DOMUtils;

import org.apache.util.HttpURL;
import org.apache.commons.httpclient.*;
import org.apache.commons.httpclient.methods.GetMethod;
import org.apache.commons.httpclient.methods.HeadMethod;
import org.apache.commons.httpclient.methods.PostMethod;
import org.apache.commons.httpclient.methods.PutMethod;
import org.apache.webdav.lib.methods.*;
import org.apache.webdav.lib.properties.ResourceTypeProperty;
import org.apache.webdav.lib.properties.LockDiscoveryProperty;
import org.apache.webdav.lib.properties.AclProperty;
import org.apache.webdav.lib.properties.PrincipalCollectionSetProperty;

/**
* The class <code>WebdavResource</code> is an abstract representation
* for WebDAV resource.<p>
*
* <pre>
* A functional comparison of WebdavResource and JDK(It's different a lot).
* ----------------------------------+-------------------------------------
*   File class (JDK 1.3.x)          |  WebdavResource class
* ----------------------------------+-------------------------------------
*   File(String)                    |  WebdavResource(HttpURL)
*   File(String, String)            |  X (need to escape)
*   File(File, String)              |  WebdavResource(HttpURL, String)
*   getName()                       |  *see getHttpURL() and HttpURL
*   getParaent()                    |  *see getHttpURL() and HttpURL
*   getParentFile()                 |  X (not yet)
*   getPath()                       |  *see getHttpURL() and HttpURL
*   isAbsolute()                    |  X
*   getAbsolutePath()               |
*   getAbsoluteFile()               |  X
*   getCanonicalPath()              |
*   getCanonicalFile()              |  X
*   toURL()                         |  *see HttpURL
*   canRead()                       | 
*   !canWrite()                     |  !isLocked()
*   exists()                        |  exists()
*   isDirectory()                   |  isCollection()
*   isFile()                        |  !isCollection()
*   isHidden()                      |  getIsHidden()
*   lastModified()                  |  getGetLastModified()
*   length()                        |  getGetContentLength()
*   createNewFile()                 |  putMethod(String)
*   delete()                        |  deleteMethod()
*   deleteOnExit()                  |  X
*   list()                          |  list()
*   list(FilenameFilter)            |  X
*   listFiles()                     |  listWebdavResources()
*   listFiles(FilenameFilter)       |  X
*   listFiles(FileFilter)           |  X
*   mkdir()                         |  mkcolMethod()
*   mkdirs()                        |  mkcolMethod()
*   renameTo(File)                  |  moveMethod(String)
*   setLastModified()               |  X
*   setReadOnly()                   |  setOverwrite(boolean)
*   listRoots()                     |  *see WebdavSession
*   generateFile()                  | 
*   createTempFile(...)             |  setGetTempDir(String)
*   compareTo(Object)               |  compareTo(Object)
*   equals(Object)                  |  equals(Object)
*   hashCode()                      |  X
* ----------------------------------+-------------------------------------
*   URL class (JDK 1.3.x)           |  Webdavresource and HttpURL classes
* ----------------------------------+-------------------------------------
*   getQuery()                      |  getQuery()
*   getPath()                       |  getPath()
*   getUserInfo()                   |  getUserInfo()
*   getAuthority()                  |  getAuthority()
*   getPort()                       |  getPort()
*   getProtocol()                   |  getScheme()
*   getHost()                       |  getHost()
*   getFile()                       |  getPath()
*   getRef()                        |  getFragmenet()
*   hashCode()                      |  X
*   sameFile()                      |
*   toExternalForm()                |  toExternalForm()
*   openConnection()                |
*   openStream()                    |
*   getContent()                    |  getMethodDataAsString()
* ----------------------------------+-------------------------------------
*   URLConnection class (JDK 1.3.x) |  HttpClient Library and more
* ----------------------------------+-------------------------------------
*   getFileNameMap()                |  X
*   setFileNameMap()                |  X
*   connect()                       |
*   getURL()                        |  HttpURL#getURL()
*   getContenetLength()()           |
*   getContentType()                |
*   getContentEncoding()            |
*   getExpiration()                 |
*   getDate()                       |
*   getLastModified()               |
*   getHeaderField()                |
*   getHeaderFieldInt()             |  X
*   getHeaderFielDate()             |  X
*   getHeaderFieldKey()             |  X
*   getHeaderFiled(int)             |  X
*   getContenet()                   | 
*   getInputStream()                |  WebdavResource#getMethodData()
*   getOutputStream()               |  WebdavResource#putMethod(...)
*   setDoInput()                    |  X
*   getDoInput()                    |  X
*   setAllowUserInteraction()       |  *see WebdavException and WebdavStatus
*   getAllowUserInteraction()       |  *see WebdavException and WebdavStatus
*   setUseCaches()                  |
*   getUseCaches()                  | 
*   getIfModifiedSince()            |  X
*   setIfModifiedSince(boolean)     |  X
*   setRequestProperty(...)         |  X
*   getRequestProperty(...)         |  X
*   guessContentTypeFromStream(...) |  X
* ----------------------------------+-------------------------------------
* </pre>
*
* @author <a href="mailto:jericho@thinkfree.com">Park, Sung-Gu</a>
* @author Dirk Verbeeck
* @author Remy Maucherat
*/
public class WebdavResource extends WebdavSession {


    // -------------------------------------------------------  Constructors


    /**
     * Default constructor.
     */
    private WebdavResource(HttpClient client) {
        super();
        this.client = client;
    }


    /**
     * The constructor.
     *
     * @param httpURL The specified http URL.
     * @param action The action to set properties of this resource.
     * @param depth The depth to find properties.
     * @exception HttpException
     * @exception IOException
     */
    public WebdavResource(HttpURL httpURL, int action, int depth)
        throws HttpException, IOException {

        setHttpURL(httpURL, action, depth);
    }


    /**
     * The constructor.
     *
     * @param httpURL The specified http URL.
     * @param depth The depth to find properties.
     * @exception HttpException
     * @exception IOException
     */
    public WebdavResource(HttpURL httpURL, int depth)
        throws HttpException, IOException {

        setHttpURL(httpURL, defaultAction, depth);

    }


    /**
     * The constructor.
     *
     * @param httpURL The specified http URL.
     * @exception HttpException
     * @exception IOException
     */
    public WebdavResource(HttpURL httpURL)
        throws HttpException, IOException {

        setHttpURL(httpURL);
    }


    /**
     * The constructor.
     * It must be put an escaped http URL as an arguement.
     *
     * @param escapedHttpURL The escaped http URL string.
     * @exception HttpException
     * @exception IOException
     */
    public WebdavResource(String escapedHttpURL)
        throws HttpException, IOException {

        setHttpURL(escapedHttpURL);
    }


    /**
     * The constructor.
     *
     * @param httpURL The http URL.
     * @param additionalPath The added relative path.
     * @exception HttpException
     * @exception IOException
     */
    public WebdavResource(HttpURL httpURL, String additionalPath)
        throws HttpException, IOException {

        setHttpURL(httpURL, additionalPath);
    }


    // -------------------------------------- Constants for WebDAV properties.


    /**
     * The displayname property.
     */
    public static final String DISPLAYNAME = "displayname";


    /**
     * The getcontentlength property.
     */
    public static final String GETCONTENTLENGTH = "getcontentlength";


    /**
     * The getlastmodifed property.
     */
    public static final String GETLASTMODIFIED = "getlastmodified";


    /**
     * The creationdate property.
     */
    public static final String CREATIONDATE = "creationdate";


    /**
     * The resourcetype property.
     */
    public static final String RESOURCETYPE = "resourcetype";


    /**
     * The getcontenttype property.
     */
    public static final String GETCONTENTTYPE = "getcontenttype";


    /**
     * The getetag property.
     */
    public static final String GETETAG = "getetag";


    /**
     * The ishidden property.
     */
    public static final String ISHIDDEN = "ishidden";


    /**
     * The iscollection property.
     */
    public static final String ISCOLLECTION = "iscollection";


    /**
     * The supportedlock property.
     */
    public static final String SUPPORTEDLOCK = "supportedlock";


    /**
     * The lockdiscovery property.
     */
    public static final String LOCKDISCOVERY = "lockdiscovery";


    // ------------------------------------------------------------ Constants


    /**
     * No action to find properties for this resource.
     */
    public static final int NOACTION = 1;
   
   
    /**
     * The action setting only the displayname for this resource.
     */
    public static final int NAME = 2;
   

    /**
     * The action setting the basic properties for this resource.
     */
    public static final int BASIC = 3;


    /**
     * The action setting the default DAV properties for this resource.
     */
    public static final int DEFAULT = 4;


    /**
     * The action setting the all properties for this resource.
     */
    public static final int ALL = 5;


    /**
     * Owner information for locking and unlocking.
     */
    public static final String defaultOwner = "Slide";


    /**
     * The true constant string.
     */
    public static final String TRUE = "1";


    /**
     * The false constant string.
     */
    public static final String FALSE = "0";


    /**
     * Date formats using for Date parsing.
     */
    public static final SimpleDateFormat formats[] = {
        new SimpleDateFormat("EEE, dd MMM yyyy HH:mm:ss zzz", Locale.US),
        new SimpleDateFormat("EEE MMM dd HH:mm:ss zzz yyyy", 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),
        new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss'Z'", Locale.US),
        new SimpleDateFormat("yyyy-MM-dd'T'HH:mm:ss.sss'Z'", Locale.US)
    };


    /**
     * GMT timezone.
     */
    protected final static TimeZone gmtZone = TimeZone.getTimeZone("GMT");


    static {
        for (int i = 0; i < formats.length; i++) {
            formats[i].setTimeZone(gmtZone);
        }
    }


    // --------------------------------------------------- Instance Variables


    /**
     * The HttpURL to represent a WebDAV resource.
     */
    private HttpURL httpURL;


    /**
     * Table of the hrefs gotten in a collection.
     */
    private WebdavResources childResources = new WebdavResources();


    /**
     * The default action to find properties.
     */
    private static int defaultAction = BASIC;


    /**
     * The default depth for WebDAV methods.
     */
    private static int defaultDepth = DepthSupport.DEPTH_0;


    /**
     * The default temporary directory for the GET method.
     */
    private static String tempDirForGet;


    /**
     * The flag setter to use the disk for the GET method.
     */
    private static boolean useDiskForGet = true;


    /**
     * The flag to set the status code by propfind.
     */
    private boolean thisResource;


    /**
     * The allowed HTTP methods.
     */
    private Enumeration allowedMethods;


    /**
     * The capabilities of the WebDAV server.
     */
    private Enumeration davCapabilities;


    /**
     * An WebdavResource flag to check its existence;
     */
    private boolean exists;


    /**
     * An WebdavResource flag to check overwriting;
     */
    private boolean overwrite;


    /**
     * An status code performed by HTTP methods at the most recent.
     */
    private int latestStatusCode;


    /**
     * An status message performed by HTTP methods at the most recent.
     */
    private String latestStatusMessage = "";


    /**
     * An WebDAV property, displayname.
     */
    private String displayName = "";


    /**
     * An WebDAV property, getcontentlength.
     */
    private long getContentLength;


    /**
     * An WebDAV property, getcontenttype.
     */
    private String getContentType = "";


    /**
     * An WebDAV property, resourcetype.
     */
    private ResourceTypeProperty resourceType;


    /**
     * An WebDAV property, getlastmodified.
     */
    private long getLastModified;


    /**
     * An WebDAV property, creationdate.
     */
    private long creationDate;


    /**
     * An WebDAV property, getetag.
     */
    private String getEtag = "";


    /**
     * An WebDAV property, ishidden.
     */
    private boolean isHidden;


    /**
     * An WebDAV property, iscollection.
     */
    private boolean isCollection;


    /**
     * An WebDAV property, supportedlock.
     */
    private String supportedLock = "";


    /**
     * An WebDAV property, lockdiscovery.
     */
    private LockDiscoveryProperty lockDiscovery;


    // ----------------------------------------------------- Private Methods


    /**
     * Generate and add the If header to the specified HTTP method.
     */
    private void generateIfHeader(HttpMethod method) {

        if (client == null)
            return;
        if (method == null)
            return;

        WebdavState state = (WebdavState) client.getState();
        String[] lockTokens = state.getAllLocks(method.getPath());
       
        if (lockTokens.length == 0)
            return;

        StringBuffer ifHeaderValue = new StringBuffer();

        for (int i = 0; i < lockTokens.length; i++) {
            ifHeaderValue.append("(<").append(lockTokens[i]).append(">) ");
        }

        method.setHeader("If", ifHeaderValue.toString());

    }


    /**
     * Parse the <code>java.util.Date</code> string for HTTP-date.
     *
     * @return The parsed date.
     */
    private Date parseDate(String dateValue) {
        // TODO: move to the common util package related to http.
        Date date = null;
        for (int i = 0; (date == null) && (i < formats.length); i++) {
            try {
                date = formats[i].parse(dateValue);
            } catch (ParseException e) {
            }
        }

        return date;
    }


    /**
     * Set only the displayname property for this resource.
     *
     * @param depth The depth to find properties.
     */
    private void setNameProperties(int depth)
        throws HttpException, IOException {

        Vector properties = new Vector();
        properties.addElement(DISPLAYNAME);

        setNamedProp(depth, properties);
    }


    /**
     * Set the basic properties like displayname, getcontentlength,
     * getcontenttype, resourcetype, getlastmodified for this resoruce.
     *
     * @param depth The depth to find properties.
     */
    private void setBasicProperties(int depth)
        throws HttpException, IOException {

        Vector properties = new Vector();
        properties.addElement(DISPLAYNAME);
        properties.addElement(GETCONTENTLENGTH);
        properties.addElement(GETCONTENTTYPE);
        properties.addElement(RESOURCETYPE);
        properties.addElement(GETLASTMODIFIED);
        properties.addElement(LOCKDISCOVERY);

        setNamedProp(depth, properties);
    }


    /**
     * Set the named properties for this resource.
     *
     * @param depth The depth.
     * @param propertyNames The property-names.
     */
    private void setNamedProp(int depth, Vector propertyNames)
        throws HttpException, IOException {

        Enumeration responses = propfindMethod(depth, propertyNames);
        setWebdavProperties(responses);
    }


    /**
     * Set all properties for this resource.
     *
     * @param depth The depth
     */
    private void setAllProp(int depth)
        throws HttpException, IOException {

        Enumeration responses = propfindMethod(depth);
        setWebdavProperties(responses);
    }


    /**
     * Set WebDAV properties following to the given http URL.
     * This method is fundamental for getting information of a collection.
     *
     * @param httpURL The parent http URL to get properties.
     * @param depth The depth.
     * @exception HttpException
     * @exception IOException The socket error with a server.
     */
    private void setWebdavProperties(Enumeration responses)
        throws HttpException, IOException {

        // Make the resources in the collection empty.
        childResources.removeAll();
        while (responses.hasMoreElements()) {

            ResponseEntity response =
                (ResponseEntity) responses.nextElement();

            boolean itself = false;
            String href = (String) response.getHref();
            if (!href.startsWith("/"))
                href = HttpURL.getPath(href);
            String httpURLPath = httpURL.getPath();
            int compared = httpURLPath.compareTo(href);
            // Compare with the href path and requested-path itself.
            if (compared == 0 || compared == -1 && href.endsWith("/") ||
                compared == 1 && httpURLPath.endsWith("/")) {
                // Set the status code for this resource.
                if (response.getStatusCode() > 0)
                    setStatusCode(response.getStatusCode());
                setExistence(true);
                itself = true;
            }

            // Get to know each resource.
            WebdavResource workingResource = new WebdavResource(client);
            workingResource.setDebug(debug);
            String displayName = null;
            // Process the resource's properties
            Enumeration properties = response.getProperties();
            while (properties.hasMoreElements()) {

                Property property = (Property) properties.nextElement();

                // ------------------------------  Checking WebDAV properties

                if (property.getLocalName().equals(DISPLAYNAME)) {
                    displayName = property.getPropertyAsString();
                    if (itself) {
                        setDisplayName(displayName);
                    } else {
                        workingResource.setHttpURL
                            (httpURL, displayName, NOACTION);
                        workingResource.setExistence(true);
                        workingResource.setOverwrite(getOverwrite());
                        workingResource.setDisplayName(displayName);
                    }
                } else
                if (property.getLocalName().equals(GETCONTENTLENGTH)) {
                    String getContentLength = property.getPropertyAsString();
                    if (itself) {
                        setGetContentLength(getContentLength);
                    } else {
                        workingResource.setGetContentLength(getContentLength);
                    }
                } else
                if (property.getLocalName().equals(RESOURCETYPE)) {
                    ResourceTypeProperty resourceType =
                        (ResourceTypeProperty) property;
                    if (itself) {
                        setResourceType(resourceType);
                    } else {
                        workingResource.setResourceType(resourceType);
                    }
                } else
                if (property.getLocalName().equals(GETCONTENTTYPE)) {
                    String getContentType = property.getPropertyAsString();
                    if (itself) {
                        setGetContentType(getContentType);
                    } else {
                        workingResource.setGetContentType(getContentType);
                    }
                } else
                if (property.getLocalName().equals(GETLASTMODIFIED)) {
                    String getLastModified = property.getPropertyAsString();
                    if (itself) {
                        setGetLastModified(getLastModified);
                    } else {
                        workingResource.setGetLastModified(getLastModified);
                    }
                } else
                if (property.getLocalName().equals(CREATIONDATE)) {
                    String creationDate = property.getPropertyAsString();
                    if (itself) {
                        setCreationDate(creationDate);
                    } else {
                        workingResource.setCreationDate(creationDate);
                    }
                } else
                if (property.getLocalName().equals(GETETAG)) {
                    String getEtag = property.getPropertyAsString();
                    if (itself) {
                        setGetEtag(getEtag);
                    } else {
                        workingResource.setGetEtag(getEtag);
                    }
                } else
                if (property.getLocalName().equals(ISHIDDEN)) {
                    String isHidden = property.getPropertyAsString();
                    if (itself) {
                        setIsHidden(isHidden);
                    } else {
                        workingResource.setIsHidden(isHidden);
                    }
                } else
                if (property.getLocalName().equals(ISCOLLECTION)) {
                    String isCollection = property.getPropertyAsString();
                    if (itself) {
                        setIsCollection(isCollection);
                    } else {
                        workingResource.setIsCollection(isCollection);
                    }
                } else
                if (property.getLocalName().equals(SUPPORTEDLOCK)) {
                    String supportedLock = property.getPropertyAsString();
                    if (itself) {
                        setSupportedLock(supportedLock);
                    } else {
                        workingResource.setSupportedLock(supportedLock);
                    }
                } else
                if (property.getLocalName().equals(LOCKDISCOVERY)) {
                    LockDiscoveryProperty lockDiscovery =
                        (LockDiscoveryProperty) property;
                    if (itself) {
                        setLockDiscovery(lockDiscovery);
                    } else {
                        workingResource.setLockDiscovery(lockDiscovery);
                    }
                }
            }
            if (displayName == null || displayName.trim().equals("")) {
                displayName = HttpURL.getName(href);
                if (itself) {
                    setDisplayName(displayName);
                } else {
                    workingResource.setHttpURL
                        (httpURL, displayName, NOACTION);
                    workingResource.setExistence(true);
                    workingResource.setOverwrite(getOverwrite());
                    workingResource.setDisplayName(displayName);
                }
            }
            if (!itself)
                childResources.addResource(displayName, workingResource);
        }
    }


    // ------------------------------------------------------------ Properties


    /**
     * Set the default action for this resource.
     *
     * ex)
     *  WebdavResource.NOACTION
     *  WebdavResource.NAME
     *  WebdavResource.BASIC
     *  WebdavResource.DEFAULT
     *  WebdavResource.ALL
     *
     * @param action The action type.
     */
    public static void setDefaultAction(int action) {
        defaultAction = action;
    }


    /**
     * Get the default action.
     *
     * @return The action type.
     */
    public static int getDefaultAction() {
        return defaultAction;
    }


    /**
     * Set the default action for this resource.
     *
     * ex)
     *   DepthSupport.DEPTH_0
     *   DepthSupport.DEPTH_1
     *   DepthSupport.DEPTH_INFINITY
     *
     * @param depth The depth.
     */
    public static void setDefaultDepth(int depth) {
        defaultDepth = depth;
    }


    /**
     * Get the default action.
     *
     * @return The depth.
     */
    public static int getDefaultDepth() {
        return defaultDepth;
    }


    /**
     * Get the default temporary directory for the GET method.
     *
     * @param tempDir The temporary directory.
     */
    public static void setGetTempDir(String tempDir) {
        tempDirForGet = tempDir;
    }


    /**
     * Get the default temporary directory for the GET method.
     * The default temporary directory is "temp/".
     *
     * @return The temporary directory path.
     *         It's set by default, if it returns null.
     */
    public static String getGetTempDir() {
        return tempDirForGet;
    }



    /**
     * Set the use disk flag for the GET method.
     *
     * @param useDisk The use disk flag.
     */
    public static void setGetUseDisk(boolean useDisk) {
        useDiskForGet = useDisk;
    }


    /**
     * Get the use disk flag for the GET method.
     *
     * @return The current flag of the use disk.
     *         By default, it's true.
     */
    public static boolean getGetUseDisk() {
        return useDiskForGet;
    }


    /**
     * Test that the httpURL is the same with the client.
     *
     * @return true if the given httpURL is the client for this resource.
     */
    private synchronized boolean isTheClient() throws MalformedURLException {
       
        HttpURL clientHttpURL =
            new HttpURL(client.getUserName(), client.getPassword(),
                        client.getHost(), client.getPort());
       
        return clientHttpURL.getAuthority().equals(httpURL.getAuthority());
    }
   
   
    /**
     * Set the client for this resource.
     *
     * @exception IOException
     */
    private void setClient() throws IOException {
        setClient(httpURL);
    }
   
   
    /**
     * Set the client for this resource and the given http URL.
     *
     * @param httpURL The http URL.
     * @exception IOException
     */
    private synchronized void setClient(HttpURL httpURL) throws IOException {
       
        if ((client == null) || ((client != null) && !isTheClient())) {
            closeSession();
            client = getSessionInstance(httpURL);
        }
    }
   

    /**
     * Set the HttpURL for this WebdavResource.
     *
     * @param httpURL the specified HttpURL.
     * @param action The action to decide properties to find.
     * @param depth The depth to find properties.
     * @exception HttpException
     * @exception IOException
     * @see #setHttpURL(java.lang.String)
     * @see #setUserInfo(java.lang.String, java.lang.String)
     * @see #setPath(java.lang.String)
     */
    public void setHttpURL(HttpURL httpURL, int action, int depth)
        throws HttpException, IOException {

        this.httpURL = httpURL;
        setClient(httpURL);
        // make its existence false
        setExistence(false);
        setProperties(action, depth);
    }


    /**
     * Set the HttpURL for this WebdavResource.
     *
     * @param httpURL the specified HttpURL.
     * @param depth The depth to find properties.
     * @exception HttpException
     * @exception IOException
     * @see #setHttpURL(java.lang.String)
     * @see #setUserInfo(java.lang.String, java.lang.String)
     * @see #setPath(java.lang.String)
     */
    public void setHttpURL(HttpURL httpURL, int depth)
        throws HttpException, IOException {

        // Follow the default action.
        setHttpURL(httpURL, defaultAction, depth);
    }


    /**
     * Set the HttpURL for this WebdavResource.
     * It must be put an escaped path part of the http URL as an arguement.
     *
     * @param httpURL The specified HttpURL.
     * @param additionalPath The added relative path.
     * @param action The action to decide properties to find.
     * @param depth The depth.
     * @exception HttpException
     * @exception IOException
     * @see #setHttpURL(java.lang.String)
     * @see #setUserInfo(java.lang.String, java.lang.String)
     * @see #setPath(java.lang.String)
     */
    public void setHttpURL
        (HttpURL httpURL, String additionalPath, int action, int depth)
        throws HttpException, IOException {

        setHttpURL(new HttpURL(httpURL, additionalPath), action, depth);
    }


    /**
     * Set the HttpURL for this WebdavResource.
     * It must be put an escaped path part of the http URL as an arguement.
     *
     * @param httpURL The specified HttpURL.
     * @param additionalPath The added relative path.
     * @param action The action to decide properties to find.
     * @exception HttpException
     * @exception IOException
     * @see #setHttpURL(java.lang.String)
     * @see #setUserInfo(java.lang.String, java.lang.String)
     * @see #setPath(java.lang.String)
     */
    public void setHttpURL
        (HttpURL httpURL, String additionalPath, int action)
        throws HttpException, IOException {

        setHttpURL(new HttpURL(httpURL, additionalPath), action, defaultDepth);
    }


    /**
     * Set the HttpURL for this WebdavResource.
     *
     * @param httpURL The specified HttpURL.
     * @param additionalPath The added relative path.
     * @exception HttpException
     * @exception IOException
     * @see #setHttpURL(java.lang.String)
     * @see #setUserInfo(java.lang.String, java.lang.String)
     * @see #setPath(java.lang.String)
     */
    public void setHttpURL(HttpURL httpURL, String additionalPath)
        throws HttpException, IOException {

        setHttpURL(new HttpURL(httpURL, additionalPath),
                   defaultAction, defaultDepth);
    }


   /**
     * Set the HttpURL for this WebdavResource.
     *
     * @param httpURL the specified HttpURL.
     * @exception HttpException
     * @exception IOException
     * @see #setHttpURL(java.lang.String)
     * @see #setUserInfo(java.lang.String, java.lang.String)
     * @see #setPath(java.lang.String)
     */
    public void setHttpURL(HttpURL httpURL)
        throws HttpException, IOException {

        setHttpURL(httpURL, defaultDepth);
    }


    /**
     * Set the HttpURL of this WebdavResource.
     * It must be put an escaped http URL as an arguement.
     *
     * @param escapedHttpURL The escaped http URL string.
     * @exception HttpException
     * @exception IOException
     * @see #setHttpURL(HttpURL)
     * @see #setUserInfo(java.lang.String, java.lang.String)
     * @see #setPath(java.lang.String)
     */
    public void setHttpURL(String escapedHttpURL)
        throws HttpException, IOException {

        setHttpURL(new HttpURL(escapedHttpURL));
    }


    /**
     * Get the HttpURL of this WebdavResource.
     *
     * @return httpURL the http URL.
     */
    public HttpURL getHttpURL() {
        return httpURL;
    }


    /**
     * Get the HttpURL except for userinfo.
     *
     * @return httpURL the http URL.
     */
    public HttpURL getHttpURLExceptForUserInfo()
        throws MalformedURLException {

        return httpURL.getHttpURLExceptForUserInfo();
    }


    /**
     * Set the path part of this WebdavResource.
     *
     * @param path the specified path.
     * @exception HttpException
     * @exception IOException
     * @see #setHttpURL(HttpURL)
     * @see #setHttpURL(java.lang.String)
     * @see #setUserInfo(java.lang.String, java.lang.String)
     */
    public void setPath(String path)
        throws HttpException, IOException {

        httpURL.setPath(path);
        setHttpURL(httpURL);
    }


    /**
     * Get the path part of this WebdavResource.
     *
     * @return the path for this WebdavResource.
     * @see #setPath(java.lang.String)
     */
    public String getPath() {
        return httpURL.getPath();
    }


    /**
     * Get the hostname of this WebdavResource.
     *
     * @return the hostname.
     * @exception MalformedURLException
     */
    public String getHost() throws MalformedURLException {
        return httpURL.getHost();
    }


    /**
     * Set the userinfo part of this WebdavResource.
     *
     * @exception MalformedURLException
     * @exception IOException
     * @see #setHttpURL(HttpURL)
     * @see #setHttpURL(java.lang.String)
     * @see #setPath(java.lang.String)
     */
    public void setUserInfo(String userName, String password)
        throws HttpException, IOException {

        httpURL.setUserInfo(userName, password);
        setHttpURL(httpURL);
    }


    // ---------------------------------------- WebDAV Property Public Methods


    /**
     * Get the value of DAV property, displayname.
     *
     * @return The displayname string.
     */
    public String getDisplayName() {
        return displayName;
    }


    /**
     * Set the value of DAV property, displayname.
     *
     * @param displayName The displayname string.
     */
    public void setDisplayName(String displayName) {
        this.displayName = displayName;
    }


    /**
     * Get the value of DAV property, getcontentlength.
     *
     * @return The getcontentlength value.
     */
    public long getGetContentLength() {
        return getContentLength;
    }


    /**
     * Set the value of DAV property, getcontentlength.
     *
     * @param getContentLength The getcontentlength value.
     */
    public void setGetContentLength(long getContentLength) {
        this.getContentLength = getContentLength;
    }


    /**
     * Set the value of DAV property, getcontentlength.
     *
     * @param getContentLength The getcontentlength value.
     */
    public void setGetContentLength(String getContentLength) {
        try {
            this.getContentLength = Long.parseLong(getContentLength);
        } catch (NumberFormatException nfe) {
            // it's ok to ignore this error.
        }
    }


    /**
     * Get the value of DAV property, resourcetype.
     *
     * @return The resourcetype property.
     * @see #isCollection()
     */
    public ResourceTypeProperty getResourceType() {
        return resourceType;
    }


    /**
     * Set the value of DAV property, resourcetype.
     *
     * @param resourceType The resourcetype property.
     */
    public void setResourceType(ResourceTypeProperty resourceType) {
        this.resourceType = resourceType;
    }


    /**
     * Get the value of DAV property, resourcetype
     *
     * @return The resourcetype string.
     * @see #getResourceType()
     * @see #getIsCollection()
     */
    public boolean isCollection() {
        if (getResourceType() == null)
            return false;
        return getResourceType().isCollection();
    }


    /**
     * Get the value of DAV property, getcontenttype.
     *
     * @return The getcontenttype string.
     */
    public String getGetContentType() {
        return getContentType;
    }


    /**
     * Set the value of DAV property, getcontenttype.
     *
     * @param getContentType The getcontenttype string.
     */
    public void setGetContentType(String getContentType) {
        this.getContentType = getContentType;
    }


    /**
     * Get the value of DAV property, getlastmodified.
     *
     * @return The getlastmodified value.
     */
    public long getGetLastModified() {
        return getLastModified;
    }


    /**
     * Set the value of DAV property, getlastmodified.
     *
     * @param getLastModified The getlastmodified value.
     * @see #setGetLastModified(java.lang.String)
     */
    public void setGetLastModified(long getLastModified) {
        this.getLastModified = getLastModified;
    }


    /**
     * Set the value of DAV property, getlastmodified.
     *
     * @param getLastModified The getlastmodified value.
     * @see #setGetLastModified(long)
     */
    public void setGetLastModified(String getLastModified) {
        Date date = parseDate(getLastModified);
        if (date != null)
            this.getLastModified = date.getTime();
    }


    /**
     * Get the value of DAV property, creationdate.
     *
     * @return The creationdate string.
     */
    public long getCreationDate() {
        return creationDate;
    }


    /**
     * Set the value of DAV property, creationdate.
     *
     * @param creationDate The creationdate string.
     */
    public void setCreationDate(long creationDate) {
        this.creationDate = creationDate;
    }


    /**
     * Set the value of DAV property, creationdate.
     *
     * @param creationDate The creationdate string.
     */
    public void setCreationDate(String creationDate) {
        Date date = parseDate(creationDate);
        if (date != null)
            this.creationDate = date.getTime();
    }


    /**
     * Get the value of DAV property, getetag.
     *
     * @return The getetag string.
     */
    public String getGetEtag() {
        return getEtag;
    }


    /**
     * Set the value of DAV property, getetag.
     *
     * @param getEtag The getetag string.
     */
    public void setGetEtag(String getEtag) {
        this.getEtag = getEtag;
    }


    /**
     * Get the value of DAV property, supportedlock.
     *
     * @return The supportedlock string.
     */
    public String getSupportedLock() {
        return supportedLock;
    }


    /**
     * Set the value of DAV property, supportedlock.
     *
     * @param supportedLock The supportedlock string.
     */
    public void setSupportedLock(String supportedLock) {
        this.supportedLock = supportedLock;
    }


    /**
     * Get the value of DAV property, lockdiscovery.
     *
     * @return The lockdiscovery property.
     */
    public LockDiscoveryProperty getLockDiscovery() {
        return lockDiscovery;
    }

    /**
     * Set the value of DAV property, lockdiscovery.
     *
     * @param lockdiscovery The lockdiscovery property.
     */
    public void setLockDiscovery(LockDiscoveryProperty lockDiscovery) {
        this.lockDiscovery = lockDiscovery;
    }


    /**
     * Get the activelock owners for this resource.
     *
     * @return An enumeration of owners.
     */
    public Enumeration getActiveLockOwners() {
        if (lockDiscovery == null)
            return null;
        Lock[] activeLocks = lockDiscovery.getActiveLocks();
        if (activeLocks == null)
            return null;
        Vector buff = new Vector();
        int count = activeLocks.length;
        for (int i = 0; i < count; i++) {
            buff.addElement(activeLocks[i].getOwner());
        }
        return buff.elements();
    }


    /**
     * Test that this resource is locked.
     *
     * @return true if it's locked.
     */
    public boolean isLocked() {
        if (lockDiscovery == null)
            return false;
        Lock[] activeLocks = lockDiscovery.getActiveLocks();
        if (activeLocks == null)
            return false;
        for (int i = 0; i < activeLocks.length; i++) {
            if (activeLocks[i].getLockType() == Lock.TYPE_WRITE)
                return true;
        }
        return false;
    }


    /**
     * Get the value of DAV property, ishidden.
     *
     * @return true if it is hidden, otherwise false.
     */
    public boolean getIsHidden() {
        return isHidden;
    }


    /**
     * Set the value of DAV property, ishidden.
     *
     * @param isHidden
     */
    public void setIsHidden(boolean isHidden) {
        this.isHidden = isHidden;
    }


    /**
     * Set the value of DAV property, ishidden.
     *
     * @param isHidden
     */
    public void setIsHidden(String isHidden) {
        this.isHidden = isHidden.equals(TRUE) ? true : false;
    }


    /**
     * Get the value of DAV property, iscollection
     *
     * @return true if it is collection, otherwise false.
     * @see #isCollection()
     */
    public boolean getIsCollection() {
        return isCollection;
    }


    /**
     * Set the value of DAV property, iscollection
     *
     * @param isCollection
     */
    public void setIsCollection(boolean isCollection) {
        this.isCollection = isCollection;
    }


    /**
     * Set the value of DAV property, iscollection
     *
     * @param isCollection
     */
    public void setIsCollection(String isCollection) {
        this.isCollection = isCollection.equals(TRUE) ? true : false;
    }


    // --------------------------------------- WebDAV Resource Public Methods


    /**
     * Set the properties for this resource.
     *
     * @param action The action to find properties for this resource.
     * @param depth The depth.
     */
    public void setProperties(int action, int depth)
        throws HttpException, IOException {

        switch (action) {
        case NAME:
            setNameProperties(depth);
        case BASIC:
            setBasicProperties(depth);
            break;
        case DEFAULT:
            // TODO: set DAV properties using by default.
            // break;
        case ALL:
            setAllProp(depth);
            break;
        case NOACTION:
        default:
            break;
        }
    }


    /**
     * Set the properties for this resource.
     *
     * @param action The action to find properties for this resource.
     */
    public void setProperties(int depth)
        throws HttpException, IOException {
       
        setProperties(defaultAction, depth);
    }

    /**
     * Refresh the properties of this resource
     * without changing the status of the previous command
     */
    private void refresh() throws HttpException,IOException
    {
        int latestStatusCode=this.latestStatusCode;
        String latestStatusMessage = this.latestStatusMessage;
        setProperties(DepthSupport.DEPTH_0);
        this.latestStatusCode=latestStatusCode;
        this.latestStatusMessage=latestStatusMessage;
    }

    /*
     * Test if it exists.
     * This is a wrapper method for getExistence.
     *
     * @return true if it exists.
     * @see #getExistence(boolean)
     */
    public boolean exists() {
        return getExistence();
    }


    /*
     * Set its existence.
     *
     * @param exists The boolean value to be set for its existence.
     */
    public void setExistence(boolean exists) {
        this.exists = exists;
    }


    /*
     * Get its existence.
     *
     * @return true if it exists.
     */
    public boolean getExistence() {
        return exists;
    }


    /**
     * Set the overwrite flag for COPY and MOVE.
     *
     * @return true if it ok with overwriting.
     */
    public void setOverwrite(boolean overwrite) {
        this.overwrite = overwrite;
    }


    /**
     * Get the current value of the overwrite flag for COPY and MOVE.
     *
     * @return true if the current flag is overwriting.
     */
    public boolean getOverwrite() {
        return overwrite;
    }


    /**
     * Close the session of this client
     */
    public void close() throws IOException {
        closeSession();
    }


    /**
     * Get the lastest value of the status message by HTTP methods.
     *
     * @return The http status string.
     */
    public String getStatusMessage() {
        return latestStatusMessage;
    }


    /**
     * Get the lastest value of the status code by HTTP methods.
     *
     * @return The http status code.
     */
    public int getStatusCode() {
        return latestStatusCode;
    }


    /**
     * Set the lastest value of the status code by HTTP methods.
     *
     * @param statusCode the HTTP status code.
     */
    public void setStatusCode(int statusCode) {
        setStatusCode(statusCode, null);
    }


    /**
     * Set the lastest value of the status code by HTTP methods.
     *
     * @param statusCode the HTTP status code.
     * @param message the additional message.
     */
    public void setStatusCode(int statusCode, String message) {

        latestStatusCode = statusCode;
        latestStatusMessage = WebdavStatus.getStatusText(statusCode) +
            " (" + statusCode + ")" + ((message == null) ? "" : message);
    }


    /**
     * Get the allowed methods, checked by HTTP OPTIONS.
     *
     * @return the allowed HTTP methods.
     * @see #optionsMethod(java.lang.String)
     */
    public Enumeration getAllowedMethods() {
        return allowedMethods;
    }


    /**
     * Get the WebDAV capabilities, checked by HTTP OPTIONS.
     *
     * @return the WebDAV capabilities.
     * @see #optionsMethod(java.lang.String)
     */
    public Enumeration getDavCapabilities() {
        return davCapabilities;
    }


    /*
     * Get all resources in this collection with the depth 1.
     *
     * @return resources in this collection with the depth 1.
     * @exception HttpException
     * @exception IOException
     */
    public WebdavResources getChildResources()
        throws HttpException, IOException {

        setProperties(DepthSupport.DEPTH_1);

        return childResources;
    }

   
    /**
     * Get an array of resources denoting the WebDAV child resources in the
     * collection of this resources.
     *
     * @return An array of child resources in this resource.
     * @exception HttpException
     * @exception IOException
     */
    public WebdavResource[] listWebdavResources()
        throws HttpException, IOException {
       
        return getChildResources().listResources();
    }
   

    /**
     * Get an array of pathnames denoting the WebDAV resources in the
     * collection denoted by this pathname.
     *
     * @return An array of pathnames denoting the resources.
     */
    public String[] list() {

        try {
            setNameProperties(DepthSupport.DEPTH_1);
        } catch (IOException e) {
            return null;
        } catch (HttpException e) {
            return null;
        }
        Enumeration hrefs = childResources.getResourceNames();

        // To be atomic.
        Vector hrefList = new Vector();
        while (hrefs.hasMoreElements()) {
            hrefList.addElement((String) hrefs.nextElement());
        }
        // Calculate the size of the string array.
        int num = hrefList.size();
        String[] pathnames = new String[num];
        for (int i = 0; i < num; i++) {
            pathnames[i] = (String) hrefList.elementAt(i);
        }

        return pathnames;
    }


    /*
     * Get an array of pathnames and basic information denoting the WebDAV
     * resources in the denoted by this pathname.
     *
     * array 0: displayname
     * array 1: getcontentlength
     * array 2: iscollection or getcontentype
     * array 3: getlastmodifieddate
     *
     * @return An array of pathnames and more denoting the resources.
     * @exception HttpException
     * @exception IOException
     */
    public Vector listBasic()
        throws HttpException, IOException {

        setBasicProperties(DepthSupport.DEPTH_1);
        Enumeration hrefs = childResources.getResourceNames();

        Vector hrefList = new Vector();
        while (hrefs.hasMoreElements()) {
            try {
                String resourceName = (String) hrefs.nextElement();
                WebdavResource currentResource =
                    childResources.getResource(resourceName);

                String[] longFormat = new String[4];
                // displayname.
                longFormat[0] = currentResource.getDisplayName();

                long length = currentResource.getGetContentLength();
                // getcontentlength
                longFormat[1] = new Long(length).toString();
                // resourcetype
                ResourceTypeProperty resourceTypeProperty =
                    currentResource.getResourceType();
                // getcontenttype
                String getContentType =
                    currentResource.getGetContentType();
                longFormat[2] = resourceTypeProperty.isCollection() ?
                    "COLLECTION" : getContentType ;
                Date date = new Date(currentResource.getGetLastModified());
                // getlastmodified
                // Save the dummy what if failed.
                longFormat[3] = (date == null) ? "-- -- ----" :
                    // Print the local fancy date format.
                    DateFormat.getDateTimeInstance().format(date);
                hrefList.addElement(longFormat);
            } catch (Exception e) {
                // FIXME: After if's gotten an exception, any solution?
                if (debug > 0)
                    e.printStackTrace();
                //log.error(e,e);
            }
        }

        return hrefList;
    }


    /**
     * Set the URL encoding flag for this http URL.
     *
     * @param encodeURLs true if it is encoded.
     * @exception MalformedURLException
     * @exception IOException
     */
    public void setEncodeURLs(boolean encodeURLs)
        throws MalformedURLException, IOException {

        State state = client.getState();
        if (state != null) {
            state.setEncodeURLs(encodeURLs);
        }
    }


    // -------------------------- General accessor to use http request methods.


    /**
     * Retrieve the current http client for this resource.
     *
     * @return The http client.
     * @see #executeHttpRequestMethod(HttpClient, HttpMethod)
     */
    public HttpClient retrieveSessionInstance()
        throws IOException {

        setClient();
        return client;
    }


    /**
     * Execute the http request method.  And get its status code.
     *
     * @param client The http client.
     * @param method The http method.
     * @return The status code.
     * @see #retrieveSessionInstance()
     */
    public int executeHttpRequestMethod(HttpClient client, HttpMethod method)
        throws IOException, HttpException {

        client.executeMethod(method);
        return method.getStatusCode();
    }


    // --------------------------------- WebDAV Request-method Public Methods

    /**
     * Updates the resource with a new set of aces
     */
    public boolean aclMethod(String path, Ace[] aces)
        throws HttpException, IOException {

        setClient();
       
        AclMethod method = new AclMethod(path);
        generateIfHeader(method);
        for (int i=0; i<aces.length ; i++) {
            Ace ace = aces[i];
            method.addAce(ace);
        }
        method.setDebug(debug);
        client.executeMethod(method);

        int statusCode = method.getStatusCode();
        setStatusCode(statusCode);
        return (statusCode >= 200 && statusCode < 300) ? true : false;
    }

    /**
     * Return the AclProperty for the resource at the given path
     * returns null if the server doesn't respond with a AclProperty
     */
    public AclProperty aclfindMethod(String path)
        throws HttpException, IOException {

        setClient();
       
        AclProperty acl = null;

        Vector properties = new Vector();
        properties.addElement(AclProperty.TAG_NAME);
       
        // Default depth=0, type=by_name
        PropFindMethod method =
            new PropFindMethod(HttpURL.getPath(path),
                               DepthSupport.DEPTH_0, properties.elements());
        method.setDebug(debug);
        client.executeMethod(method);

        Enumeration responses = method.getResponses();
        if (responses.hasMoreElements()) {
            ResponseEntity response =
                (ResponseEntity) responses.nextElement();
            String href = (String) response.getHref();

            // Set status code for this resource.
            if ((thisResource == true) && (response.getStatusCode() > 0))
                setStatusCode(response.getStatusCode());
            thisResource = false;

            Enumeration responseProperties =
                method.getResponseProperties(href);
            while (responseProperties.hasMoreElements()) {
                Property property =
                    (Property) responseProperties.nextElement();
                if (property instanceof AclProperty) {
                    acl = (AclProperty)property;
                }

            }
        }

        return acl;
    }

    /**
     * Return the PrincipalCollectionSetProperty for the resource at the given path
     * returns null if the server doesn't respond with a PrincipalCollectionSetProperty
     */
    public PrincipalCollectionSetProperty principalCollectionSetFindMethod(String path)
        throws HttpException, IOException {

        setClient();
       
        PrincipalCollectionSetProperty set = null;

        Vector properties = new Vector();
        properties.addElement(PrincipalCollectionSetProperty.TAG_NAME);
       
        // Default depth=0, type=by_name
        PropFindMethod method =
            new PropFindMethod(HttpURL.getPath(path),
                               DepthSupport.DEPTH_0, properties.elements());
        method.setDebug(debug);
        client.executeMethod(method);

        Enumeration responses = method.getResponses();
        if (responses.hasMoreElements()) {
            ResponseEntity response =
                (ResponseEntity) responses.nextElement();
            String href = (String) response.getHref();

            // Set status code for this resource.
            if ((thisResource == true) && (response.getStatusCode() > 0))
                setStatusCode(response.getStatusCode());
            thisResource = false;

            Enumeration responseProperties =
                method.getResponseProperties(href);
            while (responseProperties.hasMoreElements()) {
                Property property =
                    (Property) responseProperties.nextElement();
                if (property instanceof PrincipalCollectionSetProperty) {
                    set = (PrincipalCollectionSetProperty)property;
                }

            }
        }

        return set;
    }




    /**
     * Return the LockDiscoveryProperty for the resource at the given path
     * returns null if the server doesn't respond with a LockDiscoveryProperty
     */
    public LockDiscoveryProperty lockDiscoveryPropertyFindMethod(String path)
        throws HttpException, IOException {

        setClient();
       
        LockDiscoveryProperty set = null;

        Vector properties = new Vector();
        properties.addElement(LockDiscoveryProperty.TAG_NAME);
       
        // Default depth=0, type=by_name
        PropFindMethod method =
            new PropFindMethod(HttpURL.getPath(path),
                               DepthSupport.DEPTH_0, properties.elements());
        method.setDebug(debug);
        client.executeMethod(method);

        Enumeration responses = method.getResponses();
        if (responses.hasMoreElements()) {
            ResponseEntity response =
                (ResponseEntity) responses.nextElement();
            String href = (String) response.getHref();

            // Set status code for this resource.
            if ((thisResource == true) && (response.getStatusCode() > 0))
                setStatusCode(response.getStatusCode());
            thisResource = false;

            Enumeration responseProperties =
                method.getResponseProperties(href);
            while (responseProperties.hasMoreElements()) {
                Property property =
                    (Property) responseProperties.nextElement();
                if (property instanceof LockDiscoveryProperty) {
                    set = (LockDiscoveryProperty)property;
                }

            }
        }

        return set;
    }


    /*
     * Get InputStream for the GET method.
     *
     * @return InputStream
     * @exception HttpException
     * @exception IOException
     */
    public InputStream getMethodData()
        throws HttpException, IOException {

        setClient();
        // use disk to save by default
        GetMethod method = new GetMethod(httpURL.getPath());
        method.setUseDisk(useDiskForGet);
        if (tempDirForGet != null)
            method.setTempDir(tempDirForGet);
        method.setDebug(debug);
        client.executeMethod(method);

        return method.getData();
    }


    /*
     * Get data as a String for the GET method.
     *
     * @return InputStream
     * @exception HttpException
     * @exception IOException
     */
    public String getMethodDataAsString()
        throws HttpException, IOException {

        setClient();
        GetMethod method = new GetMethod(httpURL.getPath());
        method.setUseDisk(useDiskForGet);
        if (tempDirForGet != null)
            method.setTempDir(tempDirForGet);
        method.setDebug(debug);
        client.executeMethod(method);

        return method.getDataAsString();
    }


    /*
     * Execute the GET method for this WebdavResource path.
     *
     * @param file The local file.
     * @return true if the method is succeeded.
     * @exception HttpException
     * @exception IOException
     */
    public boolean getMethod(File file)
        throws HttpException, IOException {

        return getMethod(httpURL.getPathQuery(), file);
    }


    /*
     * Execute the GET method for the given path.
     *
     * @param path the path string.
     * @param file The local file.
     * @return true if the method is succeeded.
     * @exception HttpException
     * @exception IOException
     */
    public boolean getMethod(String path, File file)
        throws HttpException, IOException {

        setClient();
        // use disk to save by default
        GetMethod method = new GetMethod(HttpURL.getPathQuery(path), file);
        method.setUseDisk(true);
        method.setDebug(debug);
        client.executeMethod(method);

        int statusCode = method.getStatusCode();
        setStatusCode(statusCode);

        return (statusCode >= 200 && statusCode < 300) ? true : false;
    }


    /**
     * Execute the PUT method for this resource.
     *
     * @param data The byte array.
     * @return true if the method is succeeded.
     * @exception HttpException
     * @exception IOException
     */
    public boolean putMethod(byte[] data)
        throws HttpException, IOException {

        return putMethod(httpURL.getPathQuery(), data);
    }


    /**
     * Execute the PUT method for the given path.
     *
     * @param path The path string.
     * @param data The byte array.
     * @return true if the method is succeeded.
     * @exception HttpException
     * @exception IOException
     */
    public boolean putMethod(String path, byte[] data)
        throws HttpException, IOException {

        setClient();
        PutMethod method = new PutMethod(HttpURL.getPathQuery(path));
        generateIfHeader(method);
        method.sendData(data);
        method.setDebug(debug);
        client.executeMethod(method);

        int statusCode = method.getStatusCode();
        setStatusCode(statusCode);

        return (statusCode >= 200 && statusCode < 300) ? true : false;
    }


    /**
     * Execute the PUT method for this resource.
     *
     * @param is The input stream.
     * @return true if the method is succeeded.
     * @exception HttpException
     * @exception IOException
     */
    public boolean putMethod(InputStream is)
        throws HttpException, IOException {

        return putMethod(httpURL.getPathQuery(), is);
    }


    /**
     * Execute the PUT method for the given path.
     *
     * @param path The path string.
     * @param is The input stream.
     * @return true if the method is succeeded.
     * @exception HttpException
     * @exception IOException
     */
    public boolean putMethod(String path, InputStream is)
        throws HttpException, IOException {

        setClient();
        PutMethod method = new PutMethod(HttpURL.getPathQuery(path));
        generateIfHeader(method);
        method.sendData(is);
        method.setDebug(debug);
        client.executeMethod(method);

        int statusCode = method.getStatusCode();
        setStatusCode(statusCode);

        return (statusCode >= 200 && statusCode < 300) ? true : false;
    }


    /*
     * Execute the PUT method for this WebdavResource.
     *
     * @param data String</cdoe> data to send.
     * @return true if the method is succeeded.
     * @exception HttpException
     * @exception IOException
     */
    public boolean putMethod(String data)
        throws HttpException, IOException {

        boolean result = putMethod(httpURL.getPath(), data);
        if (result)
            refresh();
        return result;
    }


    /*
     * Execute the PUT method for the given path.
     *
     * @param path the path to request.
     * @param data String</cdoe> to send.
     * @return true if the method is succeeded.
     * @exception HttpException
     * @exception IOException
     */
    public boolean putMethod(String path, String data)
        throws HttpException, IOException {

        setClient();
        PutMethod method = new PutMethod(HttpURL.getPath(path));
        generateIfHeader(method);
        method.sendData(data);
        method.setDebug(debug);
        client.executeMethod(method);

        int statusCode = method.getStatusCode();
        setStatusCode(statusCode);

        return (statusCode >= 200 && statusCode < 300) ? true : false;
    }


    /*
     * Execute the PUT method for this WebdavResource.
     *
     * @param File the filename to get on local.
     * @return true if the method is succeeded.
     * @exception HttpException
     * @exception IOException
     */
    public boolean putMethod(File file)
        throws HttpException, IOException {

        boolean result = putMethod(httpURL.getPath(), file);
        if (result)
            refresh();
        return result;
    }


    /*
     * Execute the PUT method for the given path.
     *
     * @param path the relative HttpURL to request.
     * @param File the filename to get on local.
     * @return true if the method is succeeded.
     * @exception HttpException
     * @exception IOException
     */
    public boolean putMethod(String path, File file)
        throws HttpException, IOException {

        setClient();
        PutMethod method = new PutMethod(HttpURL.getPath(path));
        generateIfHeader(method);
        method.sendData(file);
        method.setDebug(debug);
        client.executeMethod(method);

        int statusCode = method.getStatusCode();
        setStatusCode(statusCode);

        return (statusCode >= 200 && statusCode < 300) ? true : false;
    }



    /*
     * Execute the PUT method for this resource from the given url.
     * It's like a streaming copy about a resource of the specified remote url
     * to another remote url of this resource.
     *
     * @param url The URL to get a resource.
     * @return true if the method is succeeded.
     * @exception HttpException
     * @exception IOException
     */
    public boolean putMethod(URL url)
        throws HttpException, IOException {

        boolean result = putMethod(httpURL.getPath(), url);
        if (result)
            refresh();
        return result;
    }


    /*
     * Execute the PUT method for the given path from the given url.
     *
     * @param path The http URL to request.
     * @param url The URL to get a resource.
     * @return true if the method is succeeded.
     * @exception HttpException
     * @exception IOException
     */
    public boolean putMethod(String path, URL url)
        throws HttpException, IOException {

        setClient();
        PutMethod method = new PutMethod(HttpURL.getPath(path));
        generateIfHeader(method);
        method.sendData(url);
        method.setDebug(debug);
        client.executeMethod(method);

        int statusCode = method.getStatusCode();
        setStatusCode(statusCode);

        return (statusCode >= 200 && statusCode < 300) ? true : false;
    }


    /*
     * Execute OPTIONS method for this WebdavResource.
     *
     * @return true if the method is succeeded.
     * @exception HttpException
     * @exception IOException
     */
    public boolean optionsMethod()
        throws HttpException, IOException {

        return optionsMethod(httpURL.getPath());
    }


    /*
     * Execute OPTIONS method for the given path.
     *
     * @param path the path string.
     * @return true if the method is succeeded.
     * @exception HttpException
     * @exception IOException
     * @see #getAllowedOptions()
     */
    public boolean optionsMethod(String path)
        throws HttpException, IOException {

        setClient();
        OptionsMethod method;
        if (path.trim().equals("*"))
            method = new OptionsMethod("*");
        else
            method = new OptionsMethod(HttpURL.getPath(path));
        method.setDebug(debug);
        client.executeMethod(method);

        int statusCode = method.getStatusCode();
        setStatusCode(statusCode);

        if  (statusCode >= 200 && statusCode < 300) {
            // check if the specific method is possbile
            allowedMethods = method.getAllowedMethods();
            // check WebDAV capabilities.
            davCapabilities = method.getDavCapabilities();
            return true;
        }

        return false;
    }


    /*
     * Execute OPTIONS method for the given path.
     *
     * @param path the path to send the request.
     * @param aMethod a method to check it's supported.
     * @return true if the method is succeeded.
     * @exception HttpException
     * @exception IOException
     */
    public boolean optionsMethod(String path, String aMethod)
        throws HttpException, IOException {

        if (aMethod != null && optionsMethod(httpURL.getPath())) {
            while (allowedMethods.hasMoreElements()) {
                if (aMethod.equalsIgnoreCase(
                    (String) allowedMethods.nextElement()))
                    return true;
            }
        }

        return false;
    }


    /*
     * Execute OPTIONS method for the given http URL.
     *
     * @param httpURL the http URL.
     * @return the allowed methods and capabilities.
     * @exception HttpException
     * @exception IOException
     */
    public Enumeration optionsMethod(HttpURL httpURL)
        throws HttpException, IOException {

        HttpClient client = getSessionInstance(httpURL, true);

        OptionsMethod method = new OptionsMethod(httpURL.getPath());
        client.executeMethod(method);

        Vector options = new Vector();
        int statusCode = method.getStatusCode();
        if  (statusCode >= 200 && statusCode < 300) {
            // check if the specific method is possbile
            Enumeration allowedMethods = method.getAllowedMethods();
            while (allowedMethods.hasMoreElements()) {
                options.addElement(allowedMethods.nextElement());
            }
            // check WebDAV capabilities.
            Enumeration davCapabilities = method.getDavCapabilities();
            while (davCapabilities.hasMoreElements()) {
                options.addElement(davCapabilities.nextElement());
            }
        }

        return options.elements();
    }


    /*
     * Execute PROPFIND method with allprop for this WebdavResource.
     * Get list of all WebDAV properties on this WebDAV resource.
     *
     * <p>Once used this method, the the status code in the 207
     * reponse is need to be set for the method of WebdavResource.
     *
     * <p>The values of DepthSupport.DEPTH_0, DepthSupport.DEPTH_1,
     * DepthSupport.DEPTH_INFINITY is possbile for the depth.
     *
     * @param depth
     * @return the response entity body that has pairs of href and properties.
     * @exception HttpException
     * @exception IOException
     */
    public Enumeration propfindMethod(int depth)
        throws HttpException, IOException {

        thisResource = true;
        return propfindMethod(httpURL.getPath(), depth);
    }


    /*
     * Execute PROPFIND method with allprop for the given path.
     * Get list of all WebDAV properties on the given resource.
     *
     * <p>Once used this method, the the status code in the 207
     * reponse is need to be set for the method of WebdavResource.
     *
     * <p>The values of DepthSupport.DEPTH_0, DepthSupport.DEPTH_1,
     * DepthSupport.DEPTH_INFINITY is possbile for the depth.
     *
     * @param path the path to request.
     * @param depth
     * @return the response entity body that has pairs of href and properties.
     * @exception HttpException
     * @exception IOException
     */
    public Enumeration propfindMethod(String path, int depth)
        throws HttpException, IOException {

        setClient();
        // Change the depth for allprop
        PropFindMethod method =
            new PropFindMethod(HttpURL.getPath(path), depth);
        method.setDebug(debug);
        // Default depth=infinity, type=allprop
        client.executeMethod(method);

        // Set status code for this resource.
        if (thisResource == true) {
            setStatusCode(method.getStatusCode());
        }
        thisResource = false;

        return method.getResponses();
    }



    /*
     * Execute PROPFIND method with by propname for theis resource.
     * Get list of named WebDAV properties on this resource.
     *
     * <p>Once used this method, the the status code in the 207
     * reponse is need to be set for the method of WebdavResource.
     *
     * <p>The values of DepthSupport.DEPTH_0, DepthSupport.DEPTH_1
     * DepthSupport.DEPTH_INFINITY is possbile for the depth.
     *
     * @param depth The depth.
     * @param properties The named properties.
     * @return The response entity body that has pairs of href and properties.
     * @exception HttpException
     * @exception IOException
     */
    public Enumeration propfindMethod(int depth, Vector properties)
        throws HttpException, IOException {

        thisResource = true;
        return propfindMethod(httpURL.getPath(), depth, properties);
    }


    /*
     * Execute PROPFIND method with by propname for the given path.
     * Get list of named WebDAV properties on the given resource.
     *
     * <p>Once used this method, the the status code in the 207
     * reponse is need to be set for the method of WebdavResource.
     *
     * <p>The values of DepthSupport.DEPTH_0, DepthSupport.DEPTH_1
     * DepthSupport.DEPTH_INFINITY is possbile for the depth.
     *
     * @param path The path to request.
     * @param depth The depth.
     * @param properties The named properties.
     * @return The response entity body that has pairs of href and properties.
     * @exception HttpException
     * @exception IOException
     */
    public Enumeration propfindMethod(String path, int depth,
                                      Vector properties)
        throws HttpException, IOException {

        setClient();
        // Change the depth for prop
        PropFindMethod method =
            new PropFindMethod(HttpURL.getPath(path), depth,
                               properties.elements());
        method.setDebug(debug);
        client.executeMethod(method);

        // Set status code for this resource.
        if (thisResource == true) {
            // Set the status code.
            setStatusCode(method.getStatusCode());
        }
        thisResource = false;

        return method.getResponses();
    }


    /*
     * Execute PROPFIND method for this WebdavResource.
     * Get list of given WebDAV properties on this WebDAV resource.
     *
     * @param property the WebDAV property to find.
     * @return Enumeration list of WebDAV properties on a resource.
     * @exception HttpException
     * @exception IOException
     */
    public Enumeration propfindMethod(String propertyName)
        throws HttpException, IOException {

        Vector property = new Vector();
        property.addElement(propertyName);

        thisResource = true;
        return propfindMethod(httpURL.getPath(), property);
    }


    /*
     * Execute PROPFIND method for the given WebdavResource path.
     * Get list of given WebDAV properties on this WebDAV resource.
     *
     * @param property the WebDAV property to find.
     * @return Enumeration list of WebDAV properties on a resource.
     * @exception HttpException
     * @exception IOException
     */
    public Enumeration propfindMethod(String path, String propertyName)
        throws HttpException, IOException {

        Vector property = new Vector();
        property.addElement(propertyName);

        thisResource = false;
        return propfindMethod(HttpURL.getPath(path), property);
    }


    /*
     * Execute PROPFIND method for this WebdavResource.
     * Get list of given WebDAV properties on this WebDAV resource.
     *
     * @param properties the WebDAV properties to find.
     * @return Enumeration list of WebDAV properties on a resource.
     * @exception HttpException
     * @exception IOException
     */
    public Enumeration propfindMethod(Vector properties)
        throws HttpException, IOException {

        thisResource = true;
        return propfindMethod(httpURL.getPath(), properties);
    }


    /*
     * Execute PROPFIND method for the given path and properties.
     * Get list of given WebDAV properties on the given resource.
     *
     * @param path the path to request for propertis.
     * @param properties the WebDAV properties to find.
     * @return Enumeration list of WebDAV properties on a resource.
     * @exception HttpException
     * @exception IOException
     */
    public Enumeration propfindMethod(String path, Vector properties)
        throws HttpException, IOException {

        setClient();
        // Default depth=0, type=by_name
        PropFindMethod method =
            new PropFindMethod(HttpURL.getPath(path), DepthSupport.DEPTH_0,
                               properties.elements());
        method.setDebug(debug);
        client.executeMethod(method);

        // It contains the results.
        Vector results = new Vector();

        Enumeration responses = method.getResponses();
        if (responses.hasMoreElements()) {
            ResponseEntity response =
                (ResponseEntity) responses.nextElement();
            String href = (String) response.getHref();

            // Set status code for this resource.
            if ((thisResource == true) && (response.getStatusCode() > 0))
                setStatusCode(response.getStatusCode());
            thisResource = false;

            Enumeration responseProperties =
                method.getResponseProperties(href);
            while (responseProperties.hasMoreElements()) {
                Property property =
                    (Property) responseProperties.nextElement();
                results.addElement
                    (DOMUtils.getTextValue(property.getElement()));
            }
        }

        return results.elements();
    }


    /*
     * Execute PROPATCH method for this WebdavResource.
     *
     * @param String propertyName in "DAV:" namespace
     * @param String propertyValue
     * @return true if the method is succeeded.
     * @exception HttpException
     * @exception IOException
     */
    public boolean proppatchMethod(String propertyName, String propertyValue)
        throws HttpException, IOException {

        boolean result = proppatchMethod
            (httpURL.getPath(), propertyName, propertyValue);
        if (result)
            refresh();
        return result;
    }

    /*
     * Execute PROPATCH method for this WebdavResource.
     *
     * @param PropertyName propertyName
     * @param String propertyValue
     * @return true if the method is succeeded.
     * @exception HttpException
     * @exception IOException
     */
    public boolean proppatchMethod(PropertyName propertyName, String propertyValue)
        throws HttpException, IOException {

        boolean result = proppatchMethod
            (httpURL.getPath(), propertyName, propertyValue);
        if (result)
            refresh();
        return result;
    }

    /*
     * Execute PROPATCH method for the given WebdavResource.
     *
     * @param path the path string.
     * @param propertyName the property name in "DAV:" namespace
     * @param propertyValue the property value.
     * @return true if the method is succeeded.
     * @exception HttpException
     * @exception IOException
     */
    public boolean proppatchMethod(String path, String propertyName,
        String propertyValue) throws HttpException, IOException {

        Hashtable property = new Hashtable();
        property.put(propertyName, propertyValue);

        return proppatchMethod(path, property);
    }

    /*
     * Execute PROPATCH method for the given WebdavResource.
     *
     * @param path the path string.
     * @param propertyName the property name.
     * @param propertyValue the property value.
     * @return true if the method is succeeded.
     * @exception HttpException
     * @exception IOException
     */
    public boolean proppatchMethod(String path, PropertyName propertyName,
        String propertyValue) throws HttpException, IOException {

        Hashtable property = new Hashtable();
        property.put(propertyName, propertyValue);

        return proppatchMethod(path, property);
    }

    /*
     * Execute PROPATCH method for this WebdavResource.
     *
     * @param properties name,value pairs to set (name can be a String or PropertyName)
     * @return true if the method is succeeded.
     * @exception HttpException
     * @exception IOException
     */
    public boolean proppatchMethod(Hashtable properties)
        throws HttpException, IOException {

        boolean result = proppatchMethod(httpURL.getPath(), properties);
        if (result)
            refresh();
        return result;
    }


    /*
     * Execute PROPATCH method for the given WebdavResource.
     *
     * @param path the path string.
     * @param properties name,value pairs to set (name can be a String or PropertyName)
     * @return true if the method is succeeded.
     * @exception HttpException
     * @exception IOException
     */
    public boolean proppatchMethod(String path, Hashtable properties)
        throws HttpException, IOException {

        setClient();
        PropPatchMethod method = new PropPatchMethod(HttpURL.getPath(path));
        generateIfHeader(method);
        Enumeration names = properties.keys();
        boolean hasSomething = false;
        if (names.hasMoreElements())
            hasSomething = true;
        while (names.hasMoreElements()) {
            Object item=names.nextElement();
            if (item instanceof String) {
                String name = (String) item;
                String value = (String) properties.get(item);
                method.addPropertyToSet(name, value);
            }
            else if (item instanceof PropertyName) {
                String name         = ((PropertyName) item).getLocalName();
                String namespaceURI = ((PropertyName) item).getNamespaceURI();
                String value        = (String) properties.get(item);
                method.addPropertyToSet(name, value, null, namespaceURI);
            }
            else {
                // unknown type, ignore
            }
        }

        if (hasSomething) {
            method.setDebug(debug);
            client.executeMethod(method);

            // Possbile Status Codes => SC_OK
            // WebdavStatus.SC_FORBIDDEN, SC_CONFLICT, SC_LOCKED, 507

            int statusCode = method.getStatusCode();
            setStatusCode(statusCode);

            if (statusCode >= 200 && statusCode < 300)
                return true;
        }

        return false;
    }


    /*
     * Execute the HEAD method for this WebdavResource.
     *
     * @return true if the method is succeeded.
     * @exception HttpException
     * @exception IOException
     */
    public boolean headMethod()
        throws HttpException, IOException {

        return headMethod(httpURL.getPath());
    }


    /*
     * Execute the HEAD method for the given path.
     *
     * @param path the path to request.
     * @return true if the method is succeeded.
     * @exception HttpException
     * @exception IOException
     */
    public boolean headMethod(String path)
        throws HttpException, IOException {

        setClient();
        HeadMethod method = new HeadMethod(HttpURL.getPath(path));
        method.setDebug(debug);
        client.executeMethod(method);

        int statusCode = method.getStatusCode();
        setStatusCode(statusCode);

        return (statusCode >= 200 && statusCode < 300) ? true : false;
    }


    /*
     * Execute the DELETE method for this WebdavResource.
     *
     * @return true if the method is succeeded.
     * @exception HttpException
     * @exception IOException
     */
    public boolean deleteMethod()
        throws HttpException, IOException {

        boolean result = deleteMethod(httpURL.getPath());
        if (result)
            refresh();
        return result;
    }


    /*
     * Execute the DELETE method for the given path.
     *
     * @param path the specified path.
     * @return true if the method is succeeded.
     * @exception HttpException
     * @exception IOException
     */
    public boolean deleteMethod(String path)
        throws HttpException, IOException {

        setClient();
        DeleteMethod method = new DeleteMethod(HttpURL.getPath(path));
        generateIfHeader(method);
        method.setDebug(debug);
        client.executeMethod(method);

        int statusCode = method.getStatusCode();
        setStatusCode(statusCode);

        return (statusCode >= 200 && statusCode < 300) ? true : false;
    }


    /*
     * Execute the MOVE method for this WebdavReource.
     *
     * @param destination the specified destination path to move.
     * @return true if the method is succeeded.
     * @exception HttpException
     * @exception IOException
     */
    public boolean moveMethod(String destination)
        throws HttpException, IOException {

        boolean result = moveMethod(httpURL.getPath(),
                                    HttpURL.getPath(destination));
        if (result)
            refresh();
        return result;
    }


    /*
     * Execute the MOVE method the given source and destination.
     *
     * @param source the specified destination as a relative HttpURL.
     * @param destination the specified destination as a relative HttpURL.
     * @return true if the method is succeeded.
     * @exception HttpException
     * @exception IOException
     */
    public boolean moveMethod(String source, String destination)
        throws HttpException, IOException {

        setClient();
        MoveMethod method = new MoveMethod(source, destination);
        generateIfHeader(method);
        method.setOverwrite(overwrite);
        method.setDebug(debug);
        client.executeMethod(method);

        // Possbile MOVE Status Codes => SC_CREATED, SC_NO_CONTENT
        // WebdavStatus.SC_FORBIDDEN, SC_CONFLICT, SC_PRECONDITION_FAILED,
        // SC_LOCKED, SC_BAD_GATEWAY
        int statusCode = method.getStatusCode();
        setStatusCode(statusCode);

        return (statusCode >= 200 && statusCode < 300) ? true : false;
    }


    /*
     * Execute the COPY method for the given destination path.
     *
     * @param destination the specified destination as a relative HttpURL.
     * @return true if the method is succeeded.
     * @exception HttpException
     * @exception IOException
     */
    public boolean copyMethod(String destination)
        throws HttpException, IOException {

        boolean result = copyMethod(httpURL.getPath(),
                                    HttpURL.getPath(destination));
        if (result)
            refresh();
        return result;
    }


    /*
     * Execute the COPY method the given source and destination.
     *
     * @param source the specified destination as a relative HttpURL.
     * @param destination the specified destination as a relative HttpURL.
     * @return true if the method is succeeded.
     * @exception HttpException
     * @exception IOException
     */
    public boolean copyMethod(String source, String destination)
        throws HttpException, IOException {

        setClient();
        CopyMethod method = new CopyMethod(source, destination);
        generateIfHeader(method);
        method.setOverwrite(overwrite);
        method.setDebug(debug);
        client.executeMethod(method);

        // Possbile COPY Status Codes => SC_CREATED, SC_NO_CONTENT
        // WebdavStatus.SC_FORBIDDEN, SC_CONFLICT, SC_PRECONDITION_FAILED,
        // SC_LOCKED, SC_BAD_GATEWAY, SC_INSUFFICIENT_STORAGE
        int statusCode = method.getStatusCode();
        setStatusCode(statusCode);

        return (statusCode >= 200 && statusCode < 300) ? true : false;
    }


    /*
     * Execute the MKCOL method for this WebdavResource.
     *
     * @return true if the method is succeeded.
     * @exception HttpException
     * @exception IOException
     */
    public boolean mkcolMethod()
        throws HttpException, IOException {

        boolean result = mkcolMethod(httpURL.getPath());
        if (result)
            refresh();
        return result;
    }


    /*
     * Execute the MKCOL method for the given path.
     *
     * @param path the specified path.
     * @return true if the method is succeeded.
     * @exception HttpException
     * @exception IOException
     */
    public boolean mkcolMethod(String path)
        throws HttpException, IOException {

        setClient();
        MkcolMethod method = new MkcolMethod(HttpURL.getPath(path));
        generateIfHeader(method);
        method.setDebug(debug);
        client.executeMethod(method);

        // Possbile MKCOL Status Codes => SC_CREATED
        // WebdavStatus.SC_FORBIDDEN, SC_METHOD_NOT_ALLOWED, SC_CONFLICT,
        // SC_LOCKED, SC_UNSUPPORTED_MEDIA_TYPE, SC_INSUFFICIENT_STORAGE

        int statusCode = method.getStatusCode();
        setStatusCode(statusCode);

        return (statusCode == 405 || statusCode >= 200 && statusCode < 300)
            ? true : false;
    }


    /*
     * Execute the LOCK method for this WebdavResource.
     *
     * @return true if the method is succeeded.
     * @exception HttpException
     * @exception IOException
     */
    public boolean lockMethod()
        throws HttpException, IOException {

        String owner = null;
        if (httpURL.getUserName() != null) {
            owner = httpURL.getUserName() + "@" + httpURL.getHost();
        } else {
            owner = defaultOwner + "@" + httpURL.getHost();
        }

        boolean result = lockMethod(httpURL.getPath(), owner, (short) 120);
        if (result)
            refresh();
        return result;
    }



    /*
     * Execute the LOCK method for this WebdavResource.
     *
     * @param the owner string.
     * @param the timetout
     * @return true if the method is succeeded.
     * @exception HttpException
     * @exception IOException
     */
    public boolean lockMethod(String owner, short timeout)
        throws HttpException, IOException {

        boolean result = lockMethod(httpURL.getPath(), owner, timeout);
        if (result)
            refresh();
        return result;
    }


    /*
     * Execute the LOCK method for the given path.
     *
     * @param path the specified path.
     * @return true if the method is succeeded.
     * @exception HttpException
     * @exception IOException
     */
    public boolean lockMethod(String path)
        throws HttpException, IOException {

        String owner = null;
        if (httpURL.getUserName() != null) {
            owner = httpURL.getUserName() + "@" + httpURL.getHost();
        } else {
            owner = defaultOwner + "@" + httpURL.getHost();
        }

        return lockMethod(path, owner, (short) 120);
    }


    /*
     * Execute the LOCK method for the given path.
     *
     * @param path the specified path.
     * @param owner The owner string.
     * @param timetout the timeout value.
     * @return true if the method is succeeded.
     * @exception HttpException
     * @exception IOException
     */
    public boolean lockMethod(String path, String owner, short timeout)
        throws HttpException, IOException {

        setClient();
        // default lock type setting
        short lockType = LockMethod.SCOPE_EXCLUSIVE;
        LockMethod method =
            new LockMethod(HttpURL.getPath(path), owner, lockType, timeout);
        generateIfHeader(method);
        method.setDebug(debug);
        client.executeMethod(method);
        String lock = method.getLockToken();
        WebdavState state = (WebdavState) client.getState();
        if (state != null) {
            state.addLock(path, lock);
        }

        // Possbile LOCK Status Codes => SC_OK
        // WebdavStatus.SC_SC_PRECONDITION_FAILED, SC_LOCKED

        int statusCode = method.getStatusCode();
        setStatusCode(statusCode, lock);
        if (statusCode >= 200 && statusCode < 300) {
            return true;
        }

        return false;
    }


    /*
     * Execute the Unlock method for this WebdavResource.
     *
     * @return true if the method is succeeded.
     * @exception HttpException
     * @exception IOException
     */
    public boolean unlockMethod()
        throws HttpException, IOException {

        boolean result = unlockMethod(httpURL.getPath());
        if (result)
            refresh();
        return result;
    }


    /*
     * Execute the Unlock method for the given path.
     *
     * @param path the specified path.
     * @return true if the method is succeeded.
     * @exception HttpException
     * @exception IOException
     */
    public boolean unlockMethod(String path)
        throws HttpException, IOException {

        setClient();
        // Get the lock for the given path.
        WebdavState state = (WebdavState) client.getState();
        // Check the given path is alright.
        path = HttpURL.getPath(path);
        String lock = state.getLock(path);
        if (lock == null)
            return false;

        // unlock for the given path.
        UnlockMethod method = new UnlockMethod(path);
        generateIfHeader(method);
        method.setLockToken(lock);
        method.setDebug(debug);
        client.executeMethod(method);

        int statusCode = method.getStatusCode();
        setStatusCode(statusCode);

        if (statusCode >= 200 && statusCode < 300) {
            state.removeLocks(path);
            return true;
        }

        return false;
    }


    // -------------------------------------------------------- Basic Methods


    /*
     * Compare to the WebdavResource object.
     *
     * @param another The another WebdavResource object.
     * @return the value 0 if the argument is equal.
     */
    public int compareToWebdavResource(WebdavResource another) {

        try {
            HttpURL anotherUrl = another.getHttpURL();

            String thisHost = httpURL.getHost();
            String anotherHost= anotherUrl.getHost();
            if (!thisHost.equalsIgnoreCase(anotherHost))
                return thisHost.compareTo(anotherHost);

            int thisPort = httpURL.getPort();
            int anotherPort= anotherUrl.getPort();
            if (thisPort != anotherPort)
                return (thisPort < anotherPort) ? -1 : 1;

            boolean thisCollection = isCollection();
            boolean anotherCollection = another.isCollection();
            if (thisCollection && !anotherCollection)
                return -1;
            if (anotherCollection && !thisCollection)
                return 1;

            String thisPath = httpURL.getPathQuery();
            String anotherPath= anotherUrl.getPathQuery();
            return thisPath.compareTo(anotherPath);
        } catch (Exception e) {
            // FIXME: not to return 0.
        }

        return 0;
    }


    /**
     * Compare to the given another object.
     *
     * @param another The another WebdavResource object.
     * @return the value 0 if another is equal.
     */
    public int compareTo(Object another) {

        if ((another != null) && (another instanceof WebdavResource)) {
            return compareToWebdavResource((WebdavResource) another);
        }

        String thisUrl = toString();
        String anotherUrl = another.toString();

        return thisUrl.compareTo(anotherUrl);
    }


    /**
     * Test the object.
     *
     * @param obj the another object.
     * @return true if it's equal.
     */
    public boolean equals(Object obj) {

        if ((obj != null) && (obj instanceof WebdavResource)) {
            return compareTo(obj) == 0;
        }
        return false;
    }


    /**
     * Return the http URL string.
     *
     * @return the http URL string.
     */
    public String toString() {
        return httpURL.toString();
    }
}
TOP

Related Classes of org.apache.webdav.lib.WebdavResource

TOP
Copyright © 2018 www.massapi.com. All rights reserved.
All source code are property of their respective owners. Java is a trademark of Sun Microsystems, Inc and owned by ORACLE Inc. Contact coftware#gmail.com.