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
[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]


---------------------------------------------------------------------
To unsubscribe, e-mail: [EMAIL PROTECTED]
For additional commands, e-mail: [EMAIL PROTECTED]

Reply via email to