You are viewing a plain text version of this content. The canonical link for it is here.
Posted to slide-dev@jakarta.apache.org by Michael Christoff <Mi...@camh.net> on 2007/02/14 01:23:13 UTC

Possible solutions to WebdavResource.exists() method

I was wondering how we could better code this method.  As it stands it is unusable for the following reason:

If one attempts to create a 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 the if one can successfully call exists() it implies the resource DOES exist making the method of limited use.

Why is this happening?  It is due to the a) the way WebdavResource objects are constructed, and b) the WebDAV specification itself.  First off, almost all of WebdavResources constructors call setHttpURL at some point.  setHttpURL in turn calls setProperties.  setProperties (by virtue of one of the methods called in its switch statement) ends up calling setNamedProp, which in turn calls the propFindMethod.

propFindMethod queries the WebDAV server as to what properties the requested resource has.  It does so by generating a WebDAV PROPFIND request.  Now according to the WebDAV spec:

"If there is an error retrieving a property then a proper error result MUST be included in the response. A request to retrieve the value of a property which does not exist is an error and MUST be noted, if the response uses a multistatus XML element, with a response XML element which contains a 404 (Not Found) status value." [1]

[1] 8.1 PROPFIND http://www.webdav.org/specs/rfc2518.html#http.methods.for.distributed.authoring

So 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;
        }
        
Now while this behaviour may be ok when one checks properties on an already-instantiated object, its less clear whether it makes sense to do this in WebdavResource's constructor.  One would assume (principal of least astonishment) that a WebdavResource object would behave more like a standard java File object, in that many of java.io.File's properties are lazy-loaded at method-call time vs instantiation time. But this would require the propFindMethod know whether the caller was a constructor or not.  (For a some potential solutions, see the end of this post).

In lieu of a fix, one can get around this issue (in an albeit kludgey way), by using the following static method to determine whether a resource exists:

public class WebdavResourceUtils
{
	public static WebdavResource getResource(HttpURL url)
      	throws IOException, HttpException
	{  
		WebdavResource wdr = null;
		try {
  
			wdr = new WebdavResource(url);

		} catch(HttpException httpe) {
  
			if (httpe.getReasonCode() == HttpStatus.SC_NOT_FOUND)
				return null; // failed because resource does not exist
			else
				throw httpe; // failed for some other reason
  
		}
  
		return wdr;
	}
}


But this is both redundant and requires a strange 'util' class.

---



///////// POSSIBLE SOLUTION #1 ///////////


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.

** However, I haven't looked into this enough to determine whether it will cause any strange side-effects. **




///////// POSSIBLE SOLUTION #2 ///////////

See http://issues.apache.org/bugzilla/show_bug.cgi?id=16642 for another possible solution to this issue.




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

Phone: (416) 535-8501 x6655
Fax:     (416) 595-6617
e-mail:  michael_christoff@camh.net

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


Re: Possible solutions to WebdavResource.exists() method

Posted by Antoine Levy-Lambert <an...@gmx.de>.
Hello Michael,

could you create a bugzilla issue for this problem ?

Best regards,

Antoine

On Feb 13, 2007, at 7:23 PM, Michael Christoff wrote:

>
> I was wondering how we could better code this method.  As it stands  
> it is unusable for the following reason:
>
> If one attempts to create a 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 the if  
> one can successfully call exists() it implies the resource DOES  
> exist making the method of limited use.
>
> Why is this happening?  It is due to the a) the way WebdavResource  
> objects are constructed, and b) the WebDAV specification itself.   
> First off, almost all of WebdavResources constructors call  
> setHttpURL at some point.  setHttpURL in turn calls setProperties.   
> setProperties (by virtue of one of the methods called in its switch  
> statement) ends up calling setNamedProp, which in turn calls the  
> propFindMethod.
>
> propFindMethod queries the WebDAV server as to what properties the  
> requested resource has.  It does so by generating a WebDAV PROPFIND  
> request.  Now according to the WebDAV spec:
>
> "If there is an error retrieving a property then a proper error  
> result MUST be included in the response. A request to retrieve the  
> value of a property which does not exist is an error and MUST be  
> noted, if the response uses a multistatus XML element, with a  
> response XML element which contains a 404 (Not Found) status  
> value." [1]
>
> [1] 8.1 PROPFIND http://www.webdav.org/specs/ 
> rfc2518.html#http.methods.for.distributed.authoring
>
> So 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;
>         }
>
> Now while this behaviour may be ok when one checks properties on an  
> already-instantiated object, its less clear whether it makes sense  
> to do this in WebdavResource's constructor.  One would assume  
> (principal of least astonishment) that a WebdavResource object  
> would behave more like a standard java File object, in that many of  
> java.io.File's properties are lazy-loaded at method-call time vs  
> instantiation time. But this would require the propFindMethod know  
> whether the caller was a constructor or not.  (For a some potential  
> solutions, see the end of this post).
>
> In lieu of a fix, one can get around this issue (in an albeit  
> kludgey way), by using the following static method to determine  
> whether a resource exists:
>
> public class WebdavResourceUtils
> {
> 	public static WebdavResource getResource(HttpURL url)
>       	throws IOException, HttpException
> 	{
> 		WebdavResource wdr = null;
> 		try {
>
> 			wdr = new WebdavResource(url);
>
> 		} catch(HttpException httpe) {
>
> 			if (httpe.getReasonCode() == HttpStatus.SC_NOT_FOUND)
> 				return null; // failed because resource does not exist
> 			else
> 				throw httpe; // failed for some other reason
>
> 		}
>
> 		return wdr;
> 	}
> }
>
>
> But this is both redundant and requires a strange 'util' class.
>
> ---
>
>
>
> ///////// POSSIBLE SOLUTION #1 ///////////
>
>
> 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.
>
> ** However, I haven't looked into this enough to determine whether  
> it will cause any strange side-effects. **
>
>
>
>
> ///////// POSSIBLE SOLUTION #2 ///////////
>
> See http://issues.apache.org/bugzilla/show_bug.cgi?id=16642 for  
> another possible solution to this issue.
>
>
>
>
> 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
>
> Phone: (416) 535-8501 x6655
> Fax:     (416) 595-6617
> e-mail:  michael_christoff@camh.net
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: slide-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: slide-dev-help@jakarta.apache.org


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


RE: Application level side effects of new exists() behaviour, plus: Slide dev list archive link not working

Posted by Michael Christoff <Mi...@camh.net>.
> Thanx for the pointer. I fixed the links on the
> mail2.html page.
> The correct url is : 
> http://mail-archives.apache.org/mod_mbox/jakarta-slide-dev/

No problem and thanks for updating the link.


Cheers,

-mike



Michael N. Christoff
Site Administrator
Continuing Professional Education Online
Centre for Addiction and Mental Health
33 Russell Street
Toronto, Ontario M5S 2S1


 


-----Original Message-----
From: Martin van den Bemt [mailto:mllist@mvdb.net]
Sent: February 17, 2007 7:41 PM
To: Slide Developers Mailing List
Subject: Re: Application level side effects of new exists() behaviour,
plus: Slide dev list archive link not working


Thanx for the pointer. I fixed the links on the mail2.html page.
The correct url is : http://mail-archives.apache.org/mod_mbox/jakarta-slide-dev/

Mvgr,
Martin

Michael Christoff wrote:
> I was wondering if someone here has the ability to fix the Slide dev mailing list archive.  Its listed as being at this URL:
> 
> http://mail-archives.eu.apache.org/mod_mbox/jakarta-slide-dev/
> 
> However, at least from within my company network, I get a "The server at mail-archives.apache.org is taking too long to respond" error when I try to access it.
> 
> ---
> 
> As for application level side-effects of the new exists() method behaviour:
> 
> Updating the propfindMethod method may introduce errors in users' code if they had 'coded around' the old behaviour of exists(). This may be something to consider when updating the API. For example: Although I haven't noticed any with respect to the behaviour of the Slide client API itself, I have found some issues relating to my own application. The code below is based on a some code from my app:
> 
> ---
> 
> WebdavResource wdrMyFile = null;
> boolean myFileDoesNotExist = false;
> 
> try {
> 	
> 	wdrMyFile = new WebdavResource(myFileHttpURL);
> 
> } catch(Exception e) {
> 
> 	myFileDoesNotExist = true;
> 
> }
> 
> if(myFileDoesNotExist)
> {
> 	System.out.println("Network error or file does not exist");
> 	return;
> }
> 
> ...
> 
> ---
> 
> As you can see, I hadn't been checking the status code to see if it was a 404 error that caused the problem.  While this will work with the old behaviour of WebdavResource, it will obviously not work with the new behaviour since the try block will no longer throw an exception so myFileDoesNotExist will be false.  However, wdrMyFile.exists() may also be false--introducing a bug in my code.  I hadn't noticed the potential problem while running the code since the simple tests I did never encountered a non-existent file.  If they had, my program would behaved incorrectly.
> 
> I've been going through my code line by line to find such situations.  The way one would need to code this so that it works for both versions of WebdavResource would be something like:
> 
> ---
> 
> WebdavResource wdrMyFile = null;
> boolean myFileDoesNotExist = false;
> boolean networkError = false;
> 
> try {
> 	
> 	wdrMyFile = new WebdavResource(myFileHttpURL);
> 
> } catch(HttpException httpe) {
> 
> 	if(httpe.getReasonCode() == HttpStatus.SC_NOT_FOUND)
> 		myFileDoesNotExist = true;
> 	else
> 		networkError = true;
> 
> } catch(IOException ioe) {
> 
> 	networkError = true;
> 
> }
> 
> if(myFileDoesNotExist || !wdrMyFile.exists())
> {
> 	System.out.println("File does not exist");
> 	return;
> }
> 
> if(networkError)
> {
> 	System.out.println("Network Error");
> 	return;
> }
> 
> ...
> 
> ---
> 
> But as you can see, this can unfortunately be a bit of pain to code.
> 
> 
> 
> Cheers!
> 
> 
> 
> Michael N. Christoff
> dmx_dawg@hotmail.com
> 
> 
> -mike
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: slide-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: slide-dev-help@jakarta.apache.org
> 
> 
> 

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


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


Re: Application level side effects of new exists() behaviour, plus: Slide dev list archive link not working

Posted by Martin van den Bemt <ml...@mvdb.net>.
Thanx for the pointer. I fixed the links on the mail2.html page.
The correct url is : http://mail-archives.apache.org/mod_mbox/jakarta-slide-dev/

Mvgr,
Martin

Michael Christoff wrote:
> I was wondering if someone here has the ability to fix the Slide dev mailing list archive.  Its listed as being at this URL:
> 
> http://mail-archives.eu.apache.org/mod_mbox/jakarta-slide-dev/
> 
> However, at least from within my company network, I get a "The server at mail-archives.apache.org is taking too long to respond" error when I try to access it.
> 
> ---
> 
> As for application level side-effects of the new exists() method behaviour:
> 
> Updating the propfindMethod method may introduce errors in users' code if they had 'coded around' the old behaviour of exists(). This may be something to consider when updating the API. For example: Although I haven't noticed any with respect to the behaviour of the Slide client API itself, I have found some issues relating to my own application. The code below is based on a some code from my app:
> 
> ---
> 
> WebdavResource wdrMyFile = null;
> boolean myFileDoesNotExist = false;
> 
> try {
> 	
> 	wdrMyFile = new WebdavResource(myFileHttpURL);
> 
> } catch(Exception e) {
> 
> 	myFileDoesNotExist = true;
> 
> }
> 
> if(myFileDoesNotExist)
> {
> 	System.out.println("Network error or file does not exist");
> 	return;
> }
> 
> ...
> 
> ---
> 
> As you can see, I hadn't been checking the status code to see if it was a 404 error that caused the problem.  While this will work with the old behaviour of WebdavResource, it will obviously not work with the new behaviour since the try block will no longer throw an exception so myFileDoesNotExist will be false.  However, wdrMyFile.exists() may also be false--introducing a bug in my code.  I hadn't noticed the potential problem while running the code since the simple tests I did never encountered a non-existent file.  If they had, my program would behaved incorrectly.
> 
> I've been going through my code line by line to find such situations.  The way one would need to code this so that it works for both versions of WebdavResource would be something like:
> 
> ---
> 
> WebdavResource wdrMyFile = null;
> boolean myFileDoesNotExist = false;
> boolean networkError = false;
> 
> try {
> 	
> 	wdrMyFile = new WebdavResource(myFileHttpURL);
> 
> } catch(HttpException httpe) {
> 
> 	if(httpe.getReasonCode() == HttpStatus.SC_NOT_FOUND)
> 		myFileDoesNotExist = true;
> 	else
> 		networkError = true;
> 
> } catch(IOException ioe) {
> 
> 	networkError = true;
> 
> }
> 
> if(myFileDoesNotExist || !wdrMyFile.exists())
> {
> 	System.out.println("File does not exist");
> 	return;
> }
> 
> if(networkError)
> {
> 	System.out.println("Network Error");
> 	return;
> }
> 
> ...
> 
> ---
> 
> But as you can see, this can unfortunately be a bit of pain to code.
> 
> 
> 
> Cheers!
> 
> 
> 
> Michael N. Christoff
> dmx_dawg@hotmail.com
> 
> 
> -mike
> 
> 
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: slide-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: slide-dev-help@jakarta.apache.org
> 
> 
> 

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


Application level side effects of new exists() behaviour, plus: Slide dev list archive link not working

Posted by Michael Christoff <Mi...@camh.net>.
I was wondering if someone here has the ability to fix the Slide dev mailing list archive.  Its listed as being at this URL:

http://mail-archives.eu.apache.org/mod_mbox/jakarta-slide-dev/

However, at least from within my company network, I get a "The server at mail-archives.apache.org is taking too long to respond" error when I try to access it.

---

As for application level side-effects of the new exists() method behaviour:

Updating the propfindMethod method may introduce errors in users' code if they had 'coded around' the old behaviour of exists(). This may be something to consider when updating the API. For example: Although I haven't noticed any with respect to the behaviour of the Slide client API itself, I have found some issues relating to my own application. The code below is based on a some code from my app:

---

WebdavResource wdrMyFile = null;
boolean myFileDoesNotExist = false;

try {
	
	wdrMyFile = new WebdavResource(myFileHttpURL);

} catch(Exception e) {

	myFileDoesNotExist = true;

}

if(myFileDoesNotExist)
{
	System.out.println("Network error or file does not exist");
	return;
}

...

---

As you can see, I hadn't been checking the status code to see if it was a 404 error that caused the problem.  While this will work with the old behaviour of WebdavResource, it will obviously not work with the new behaviour since the try block will no longer throw an exception so myFileDoesNotExist will be false.  However, wdrMyFile.exists() may also be false--introducing a bug in my code.  I hadn't noticed the potential problem while running the code since the simple tests I did never encountered a non-existent file.  If they had, my program would behaved incorrectly.

I've been going through my code line by line to find such situations.  The way one would need to code this so that it works for both versions of WebdavResource would be something like:

---

WebdavResource wdrMyFile = null;
boolean myFileDoesNotExist = false;
boolean networkError = false;

try {
	
	wdrMyFile = new WebdavResource(myFileHttpURL);

} catch(HttpException httpe) {

	if(httpe.getReasonCode() == HttpStatus.SC_NOT_FOUND)
		myFileDoesNotExist = true;
	else
		networkError = true;

} catch(IOException ioe) {

	networkError = true;

}

if(myFileDoesNotExist || !wdrMyFile.exists())
{
	System.out.println("File does not exist");
	return;
}

if(networkError)
{
	System.out.println("Network Error");
	return;
}

...

---

But as you can see, this can unfortunately be a bit of pain to code.



Cheers!



Michael N. Christoff
dmx_dawg@hotmail.com


-mike


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


RE: Possible solutions to WebdavResource.exists() method

Posted by Michael Christoff <Mi...@camh.net>.
Hi Antoine.

The three methods of 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).

Cheers!

Mike N. Christoff

---------------

    /**
     * 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();
    }    



Cheers!

-mike

-----Original Message-----
From: Antoine Levy-Lambert [mailto:antoine@gmx.de]
Sent: February 13, 2007 10:37 PM
To: Slide Developers Mailing List
Subject: Re: Possible solutions to WebdavResource.exists() method


Hello Michael,

I like your solution of adding a test for NOT_FOUND.

I will work on this as soon as I can.

Best regards,

Antoine
On Feb 13, 2007, at 7:23 PM, Michael Christoff wrote:


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


Re: Possible solutions to WebdavResource.exists() method

Posted by Antoine Levy-Lambert <an...@gmx.de>.
Hello Michael,

I like your solution of adding a test for NOT_FOUND.

I will work on this as soon as I can.

Best regards,

Antoine
On Feb 13, 2007, at 7:23 PM, Michael Christoff wrote:

>
> I was wondering how we could better code this method.  As it stands  
> it is unusable for the following reason:
>
> If one attempts to create a 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 the if  
> one can successfully call exists() it implies the resource DOES  
> exist making the method of limited use.
>
> Why is this happening?  It is due to the a) the way WebdavResource  
> objects are constructed, and b) the WebDAV specification itself.   
> First off, almost all of WebdavResources constructors call  
> setHttpURL at some point.  setHttpURL in turn calls setProperties.   
> setProperties (by virtue of one of the methods called in its switch  
> statement) ends up calling setNamedProp, which in turn calls the  
> propFindMethod.
>
> propFindMethod queries the WebDAV server as to what properties the  
> requested resource has.  It does so by generating a WebDAV PROPFIND  
> request.  Now according to the WebDAV spec:
>
> "If there is an error retrieving a property then a proper error  
> result MUST be included in the response. A request to retrieve the  
> value of a property which does not exist is an error and MUST be  
> noted, if the response uses a multistatus XML element, with a  
> response XML element which contains a 404 (Not Found) status  
> value." [1]
>
> [1] 8.1 PROPFIND http://www.webdav.org/specs/ 
> rfc2518.html#http.methods.for.distributed.authoring
>
> So 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;
>         }
>
> Now while this behaviour may be ok when one checks properties on an  
> already-instantiated object, its less clear whether it makes sense  
> to do this in WebdavResource's constructor.  One would assume  
> (principal of least astonishment) that a WebdavResource object  
> would behave more like a standard java File object, in that many of  
> java.io.File's properties are lazy-loaded at method-call time vs  
> instantiation time. But this would require the propFindMethod know  
> whether the caller was a constructor or not.  (For a some potential  
> solutions, see the end of this post).
>
> In lieu of a fix, one can get around this issue (in an albeit  
> kludgey way), by using the following static method to determine  
> whether a resource exists:
>
> public class WebdavResourceUtils
> {
> 	public static WebdavResource getResource(HttpURL url)
>       	throws IOException, HttpException
> 	{
> 		WebdavResource wdr = null;
> 		try {
>
> 			wdr = new WebdavResource(url);
>
> 		} catch(HttpException httpe) {
>
> 			if (httpe.getReasonCode() == HttpStatus.SC_NOT_FOUND)
> 				return null; // failed because resource does not exist
> 			else
> 				throw httpe; // failed for some other reason
>
> 		}
>
> 		return wdr;
> 	}
> }
>
>
> But this is both redundant and requires a strange 'util' class.
>
> ---
>
>
>
> ///////// POSSIBLE SOLUTION #1 ///////////
>
>
> 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.
>
> ** However, I haven't looked into this enough to determine whether  
> it will cause any strange side-effects. **
>
>
>
>
> ///////// POSSIBLE SOLUTION #2 ///////////
>
> See http://issues.apache.org/bugzilla/show_bug.cgi?id=16642 for  
> another possible solution to this issue.
>
>
>
>
> 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
>
> Phone: (416) 535-8501 x6655
> Fax:     (416) 595-6617
> e-mail:  michael_christoff@camh.net
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: slide-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: slide-dev-help@jakarta.apache.org


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