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
*** This bug has been marked as a duplicate of 16642 ***