Re: Possible solutions to WebdavResource.exists() method

Antoine Levy-Lambert <[email protected]> Sun, 25 Feb 2007 16:46:24 -0500
Newsgroups gmane.comp.jakarta.slide.devel
Message-ID <[email protected]>
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
> [email protected]
>
>
>
> 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:  [email protected]
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: [email protected]
> For additional commands, e-mail: [email protected]