Bug 41750 - WebdavResource.exists() throws exception if resource does not exist
Summary: WebdavResource.exists() throws exception if resource does not exist
Status: RESOLVED DUPLICATE of bug 16642
Alias: None
Product: Slide
Classification: Unclassified
Component: WebDAV client (show other bugs)
Version: 2.1
Hardware: All All
: P2 normal (vote)
Target Milestone: ---
Assignee: Slide Developer List
URL:
Keywords:
Depends on:
Blocks:
 
Reported: 2007-03-02 13:49 UTC by Michael N. Christoff
Modified: 2007-03-30 11:21 UTC (History)
0 users



Attachments

Note You need to log in before you can comment on or make changes to this bug.
Description Michael N. Christoff 2007-03-02 13:49:05 UTC
Issue:
If one attempts to create a org.apache.webdav.lib.WebdavResource object for a 
resource that does not exist, the WebdavResource constructor will throw an 
exception and hence one can never even call exists().  So if one can even 
successfully call exists() it implies the resource DOES exist making the method 
of limited use.

Why it is occuring:
What's happening is that WebdavResource is using PROPFIND to get properties for 
a resource that does not exist which--according to the Webdav spec--is an 
error.  Hence a correct WebDAV server must return a 404 (Not Found) response. 
The code in propFindMethod (see snippet below) checks the response status and 
throws an exception if it doesn't recieve an XML multistatus response or an 
HTTP 200 (OK) response.

        if (status != HttpStatus.SC_MULTI_STATUS
            && status != HttpStatus.SC_OK) {
            HttpException ex = new HttpException();
            ex.setReasonCode(status);
            throw ex;
        }

///////////////////////////////////////
        
Solution idea:
Here is one I thought of.  We simply add the following to this conditional:

        if (status != HttpStatus.SC_MULTI_STATUS
            && status != HttpStatus.SC_OK
            
            && status != HttpStatus.SC_NOT_FOUND // <---
            
            ) {
            HttpException ex = new HttpException();
            ex.setReasonCode(status);
            throw ex;
        }

What this essentially says is "if the property does not exist, we simply won't 
add it to the Enumeration of properties, but we won't throw an exception unless 
there is a server error".  So if the user loops through the Enumeration without 
finding the requested property, the client must assume it doesn't exist.


///////////////////////////////////////
 FIX BELOW (3 methods)
///////////////////////////////////////

The three methods of org.apache.webdav.lib.WebdavResource where this change 
needs to be made are:

	propfindMethod(String, int)
	propfindMethod(String, int, Vector)
	propfindMethod(String, Vector)

The code with the updates is below.  For what its worth, my Slide-client based 
code is working without a hitch with the changes.  Also, once I re-code 
sections of my app to take advantage of the now-working exists() function, my 
code should also run faster (since I can determine whether a file exists or not 
without possibly incurring exception throw/catch overhead).

//---------------


    /**
     * 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 server relative path of the resource to request
     * @param depth
     * @return an enumeration of <code>ResponseEntity</code>
     * @exception HttpException
     * @exception IOException
     */
    public Enumeration propfindMethod(String path, int depth)
        throws HttpException, IOException {

        setClient();
        // Change the depth for allprop
        PropFindMethod method = new PropFindMethod(URIUtil.encodePath(path),
                                                   depth);

        method.setDebug(debug);

        // Default depth=infinity, type=allprop
        generateTransactionHeader(method);
        int status = client.executeMethod(method);

        // Set status code for this resource.
        if (thisResource == true) {
            setStatusCode(status);
        }
        // Also accept OK sent by buggy servers.
        
        /**
         * OLD CODE
        if (status != HttpStatus.SC_MULTI_STATUS
            && status != HttpStatus.SC_OK) {
            HttpException ex = new HttpException();
            ex.setReasonCode(status);
            throw ex;
        }
        */

        // FIX
        if (status != HttpStatus.SC_MULTI_STATUS
            
            && status != HttpStatus.SC_NOT_FOUND    // <---
            
            && status != HttpStatus.SC_OK
            ) {
            HttpException ex = new HttpException();
            ex.setReasonCode(status);
            throw ex;
        }        
       // END FIX
        
        thisResource = false;

        return method.getResponses();
    }
    
    
//---------------    

    
    public Enumeration propfindMethod(String path, int depth,
                                      Vector properties)
        throws HttpException, IOException {

        setClient();
        // Change the depth for prop
        PropFindMethod method = new PropFindMethod(URIUtil.encodePath(path),
                                                   depth,
                                                   properties.elements());

        method.setDebug(debug);
        method.setFollowRedirects(this.followRedirects);
        generateTransactionHeader(method);
        int status = client.executeMethod(method);

        // Set status code for this resource.
        if (thisResource == true) {
            // Set the status code.
            setStatusCode(method.getStatusLine().getStatusCode());
        }
        // Also accept OK sent by buggy servers.
        
        /*
         * OLD CODE
         *
        if (status != HttpStatus.SC_MULTI_STATUS
            && status != HttpStatus.SC_OK) {
            HttpException ex = new HttpException();
            ex.setReasonCode(status);
            throw ex;
        }
        */
        
        // FIX
        if (status != HttpStatus.SC_MULTI_STATUS
            
            && status != HttpStatus.SC_NOT_FOUND // <---
            
            && status != HttpStatus.SC_OK) {
            HttpException ex = new HttpException();
            ex.setReasonCode(status);
            throw ex;
        }
        // END FIX
        

        thisResource = false;

        return method.getResponses();
    }
    
    
//---------------    
    
    
    /**
     * Execute PROPFIND method for the given path and properties.
     * Get list of given WebDAV properties on the given resource.
     *
     * @param path the server relative path of the resource to request
     * @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(URIUtil.encodePath(path),
                                                   DepthSupport.DEPTH_0,
                                                   properties.elements());
        method.setDebug(debug);
        method.setFollowRedirects(this.followRedirects);
        generateTransactionHeader(method);
        int status = client.executeMethod(method);

        // Also accept OK sent by buggy servers.
        /*
         * OLD CODE
         *        
        if (status != HttpStatus.SC_MULTI_STATUS
            && status != HttpStatus.SC_OK) {
            HttpException ex = new HttpException();
            ex.setReasonCode(status);
            throw ex;
        }
        */
        
        // FIX
        if (status != HttpStatus.SC_MULTI_STATUS
            
            && status != HttpStatus.SC_NOT_FOUND	// <---
            
            && status != HttpStatus.SC_OK) {
            HttpException ex = new HttpException();
            ex.setReasonCode(status);
            throw ex;
        }
        // END FIX
        

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

        Enumeration responses = method.getResponses();
        if (responses.hasMoreElements()) {
            ResponseEntity response =
                (ResponseEntity) responses.nextElement();
            String href = 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(property.getPropertyAsString());
            }
        }

        return results.elements();
    }    

///////////////////////////////////////
///////////////////////////////////////


For more detailed information on this issue, please the following message in 
the Slide client dev mailing list archive.

Possible solutions to WebdavResource.exists() method
http://mail-archives.apache.org/mod_mbox/jakarta-slide-dev/200702.mbox/%
3c2FCCD448BA412B4FB9039AF8DDC103BC052B3FAB@camhems-1.camh.ca%3e

Possible side-effects of proposed fix
http://mail-archives.apache.org/mod_mbox/jakarta-slide-dev/200702.mbox/%
3c2FCCD448BA412B4FB9039AF8DDC103BC052B3FE3@camhems-1.camh.ca%3e




Cheers!



Michael N. Christoff
dmx_dawg@hotmail.com



///////////////////////////////////////


Michael N. Christoff
Site Administrator
Continuing Professional Education Online
Centre for Addiction and Mental Health
33 Russell Street
Toronto, Ontario M5S 2S1
Comment 1 Antoine Levy-Lambert 2007-03-30 11:21:28 UTC

*** This bug has been marked as a duplicate of 16642 ***