I have a mature application working with client webdavlib 2.0, with the webdav server that comes with tomcat 5.0.28. Client webdavlib 2.1 seams to be broken. Method listWebdavResources() doesn't return child collections, but the parent collection itself. This is the directory structure I tested: parent/ child1/ child2/ file1.txt file2.txt This is my code: HttpURL url = new HttpURL("http://localhost:8080/webdav/[some-url]"); url.setUserinfo("user", "pass"); WebdavResource wdResource = new WebdavResource(url); WebdavResource[] webdavList = wdResource.listWebdavResources(); System.out.println("Display Name: " + wdResource.getDisplayName()); WebdavResource[] webdavList = null; webdavList = wdResource.listWebdavResources(); System.out.println("Children returned: " + webdavList.length); for (int idx = 0; idx < webdavList.length; idx++) { System.out.println("\t" + webdavList[idx].getDisplayName()); System.out.println("\t" + webdavList[idx].getHttpURL()); } This is the output: Display Name: parent Children returned: 3 file1.txt http://localhost:8080/webdav/parent/file1.txt child2 http://localhost:8080/webdav/parent/ file2.txt http://localhost:8080/webdav/parent/file2.txt The third result is the URL of the parent, with display name "child2"! So nothing about child1, although it comes from the server (see trace). And child2 URL is bad, because it shows parent URL. In general, I see that collection childs are never shown. And this is the http tracing I got. There are two requests involved, the first using depth 0 and the second using depth 1. FIRST REQUEST =============== PROPFIND /webdav/parent HTTP/1.1 Authorization: Basic anVncmVnbzE6cGFkZW50cm8= Content-Type: text/xml; charset=utf-8 User-Agent: Jakarta Commons-HttpClient/2.0final Host: localhost:8080 Content-Length: 207 Depth: 0 <?xml version="1.0" encoding="utf-8"?> <D:propfind xmlns:D="DAV:"> <D:prop> <D:displayname/> <D:getcontentlength/> <D:getcontenttype/> <D:resourcetype/> <D:getlastmodified/> <D:lockdiscovery/> </D:prop> </D:propfind> FIRST RESPONSE ================= HTTP/1.1 207 Multi-Estado Content-Type: text/xml;charset=UTF-8 Content-Length: 436 Date: Thu, 30 Dec 2004 09:51:45 GMT Server: Apache-Coyote/1.1 <?xml version="1.0" encoding="utf-8"?> <multistatus xmlns="DAV:"> <response> <href>/webdav/parent/</href> <propstat> <prop> <displayname><![CDATA[parent]]></displayname> <resourcetype> <collection/> </resourcetype> </prop> <status>HTTP/1.1 200 OK</status> </propstat> <propstat> <prop> <getcontentlength/> <getcontenttype/> <getlastmodified/> <lockdiscovery/> </prop> <status>HTTP/1.1 404 Not Found</status> </propstat> </response> </multistatus> SECOND REQUEST ================ PROPFIND /webdav/parent HTTP/1.1 Authorization: Basic anVncmVnbzE6cGFkZW50cm8= Content-Type: text/xml; charset=utf-8 User-Agent: Jakarta Commons-HttpClient/2.0final Host: localhost:8080 Content-Length: 207 Depth: 1 <?xml version="1.0" encoding="utf-8"?> <D:propfind xmlns:D="DAV:"> <D:prop> <D:displayname/> <D:getcontentlength/> <D:getcontenttype/> <D:resourcetype/> <D:getlastmodified/> <D:lockdiscovery/> </D:prop> </D:propfind> SECOND RESPONSE ================= HTTP/1.1 207 Multi-Estado Content-Type: text/xml;charset=UTF-8 Content-Length: 2028 Date: Thu, 30 Dec 2004 09:51:45 GMT Server: Apache-Coyote/1.1 <?xml version="1.0" encoding="utf-8"?> <multistatus xmlns="DAV:"> <response> <href>/webdav/parent/</href> <propstat> <prop> <displayname><![CDATA[parent]]></displayname> <resourcetype> <collection/> </resourcetype> </prop> <status>HTTP/1.1 200 OK</status> </propstat> <propstat> <prop> <getcontentlength/> <getcontenttype/> <getlastmodified/> <lockdiscovery/> </prop> <status>HTTP/1.1 404 Not Found</status> </propstat> </response> <response> <href>/webdav/parent/file2.txt</href> <propstat> <prop> <displayname><![CDATA[file2.txt]]></displayname> <getcontentlength>10</getcontentlength> <getcontenttype>text/plain</getcontenttype> <resourcetype/> <getlastmodified>Mon, 27 Sep 2004 11:13:07 GMT</getlastmodified> </prop> <status>HTTP/1.1 200 OK</status> </propstat> <propstat> <prop> <lockdiscovery/> </prop> <status>HTTP/1.1 404 Not Found</status> </propstat> </response> <response> <href>/webdav/parent/file1.txt</href> <propstat> <prop> <displayname><![CDATA[file1.txt]]></displayname> <getcontentlength>10</getcontentlength> <getcontenttype>text/plain</getcontenttype> <resourcetype/> <getlastmodified>Mon, 27 Sep 2004 11:13:07 GMT</getlastmodified> </prop> <status>HTTP/1.1 200 OK</status> </propstat> <propstat> <prop> <lockdiscovery/> </prop> <status>HTTP/1.1 404 Not Found</status> </propstat> </response> <response> <href>/webdav/parent/child2/</href> <propstat> <prop> <displayname><![CDATA[child2]]></displayname> <resourcetype> <collection/> </resourcetype> </prop> <status>HTTP/1.1 200 OK</status> </propstat> <propstat> <prop> <getcontentlength/> <getcontenttype/> <getlastmodified/> <lockdiscovery/> </prop> <status>HTTP/1.1 404 Not Found</status> </propstat> </response> <response> <href>/webdav/parent/child1/</href> <propstat> <prop> <displayname><![CDATA[child1]]></displayname> <resourcetype> <collection/> </resourcetype> </prop> <status>HTTP/1.1 200 OK</status> </propstat> <propstat> <prop> <getcontentlength/> <getcontenttype/> <getlastmodified/> <lockdiscovery/> </prop> <status>HTTP/1.1 404 Not Found</status> </propstat> </response> </multistatus> As you can see from the second response, all the resources are returned correctly from the server.
I have a very similar problem: when I listWebdavResources() on a collection, only the first child collection is returned, and its path is wrong (it is the path of the parent). This worked with 2.0 but not in 2.1. What is the status of this bug? If it is genuine and not an error in usage, I am suprised anyone can use this version.
(In reply to comment #1) > I have a very similar problem: when I listWebdavResources() on a collection, > only the first child collection is returned, and its path is wrong (it is the > path of the parent). This worked with 2.0 but not in 2.1. > > What is the status of this bug? If it is genuine and not an error in usage, I > am suprised anyone can use this version. I am afraid few people use other WEBDAV servers than Slide. I guess this is not a problem with Slide server... Are you Rob using Slide server? I'll patiently wait for a new release of this library, 2.1 is not usable for me.
(In reply to comment #2) No, I'm using the Apache webdav server. 2.1 isn't usable for me either. I was hoping it may fix some problem with escaped url's (bug #33136)
(In reply to comment #3) > (In reply to comment #2) > No, I'm using the Apache webdav server. > 2.1 isn't usable for me either. I was hoping it may fix some problem with > escaped url's (bug #33136) I have the same problem accessing a DAV server running on IIS 5.1. In addition, list() also returns the parent, rather than listing its contents
I experienced the same problem using the slide WebDAV client library against subversion 1.1.3.
I think I had reported this too. I traced this down to the following: In WebdavResource, line 1086: URIUtil.getName(href) is used to get the name of the item; however as per the javadocs this method returns an empty string if href ends with a slash. At least with subversion, all hrefs to collections are reported as ending with a slash; therefore no sub-collections are ever reported by the WebdavResource.listWebdavResources() or associated methods. My fix: replace URIUtil.getName(href) with WebdavResource.getName(href) this seems to work fine for me; although as I said I am not sure what, if any, implications this might have on other functionality.
(In reply to comment #6) I tried this solution because I saw your post before reporting the bug. It didn't solve my problem.
(In reply to comment #6) > I think I had reported this too. I traced this down to the following: > > In WebdavResource, line 1086: URIUtil.getName(href) is used to get the name of > the item; however as per the javadocs this method returns an empty string if > href ends with a slash. At least with subversion, all hrefs to collections are > reported as ending with a slash; therefore no sub-collections are ever reported > by the WebdavResource.listWebdavResources() or associated methods. > > My fix: replace URIUtil.getName(href) with WebdavResource.getName(href) this > seems to work fine for me; although as I said I am not sure what, if any, > implications this might have on other functionality. Thanks for this suggestion. I too looked into the source code and found this to be the problem. But the solution I used was to add the following lines href = href.endsWith("/") ? href.substring(0,href.length() - 1) : href; href=href.replaceAll("\\[","%5B"); href=href.replaceAll("\\]","%5D"); href=href.replaceAll("\\|","%7C"); href=href.replaceAll("\\^","%5E"); href=href.replaceAll("\\`","%60"); This I found to work perfectly. And the reason for the replaces statments is to encode all special charaters that the exchange server might return. I suppose that this would be better done with the URLEncoder. This seems to be a long standing issue and because the fix is so simple I do not know why it has not been implemented yet. I will be using my modified class until the changes are implemented in the official source code.
Fix committed to HEAD. If no one finds any problems with it I'll backport it to the 2.1 branch. I used Robert's fix, but I tweaked the getName() method a bit. It was decoding the name which made anything with spaces in it invalid.
*** Bug 22585 has been marked as a duplicate of this bug. ***
*** Bug 32470 has been marked as a duplicate of this bug. ***
Thanks indeed, today's cvs version of webdavclient runs smoothly (2.2pre1). I think I'll wait for 2.2 to be released, instead of getting 2.1 patched (I'll jump over it!) regards, canrull
With regard to bug 32886 http://issues.apache.org/bugzilla/show_bug.cgi?id=32886 I was wondering what version of the Slide client API the fix was put in, as I get the same error described in this bug with the 2.1 binary version I downloaded off the website today. I assume I'd need to use a 2.2 beta or release candidate(?) More info: Folder structure is below ('+' denotes folder, '-' denotes file. Note: these symbols are not part of the file name): http://dav.biscu.com/ +NewFolder1 +A New Folder +SubSubFolder -MyDocsOnline.txt -TestFileUpload.txt -MyDocsOnline.txt -TestFileUpload.txt +NewFolder3 -MyDocsOnline.txt -TestFileUpload.txt -MyDocsOnline.txt -TestFileUpload.txt +NewFolder -MyDocsOnline.txt -TestFileUpload.txt The code I used to test is below: HttpURL url = new HttpURL("http://dav.Biscu.com/"); url.setUserinfo("dmx_dawg@hotmail.com", "TUSu_618"); WebdavResource wdr = new WebdavResource(url); recurseResources(wdr, 0); public void recurseResources(WebdavResource parent, int depth) throws Exception { int MAX_DEPTH = 3; if(depth > MAX_DEPTH || parent == null) return; WebdavResource[] wdrsArray = parent.listWebdavResources(); for(WebdavResource r : wdrsArray) { String s = r.isCollection() ? "[COLLECTION] " : "[FILE] "; System.out.println(repeat("\t", depth) + s + r.getDisplayName ()); if(r.isCollection()) recurseResources(r, depth + 1); } } public String repeat(String s, int n) { StringBuffer sb = new StringBuffer(); for(int i = 0; i < n; ++i) sb.append(s); return sb.toString(); } The output was: [FILE] TestFileUpload.txt [FILE] MyDocsOnline.txt [COLLECTION] NewFolder2 [FILE] TestFileUpload.txt [FILE] MyDocsOnline.txt [COLLECTION] NewFolder2 [FILE] TestFileUpload.txt [FILE] MyDocsOnline.txt [COLLECTION] NewFolder2 [FILE] TestFileUpload.txt [FILE] MyDocsOnline.txt [COLLECTION] NewFolder2
I bumped into the problem as well. 2.1 didn't work for me. A solution was to change a part of WebdavResource.setWebdavProperties after if (!itself) { String myURI = httpURL.getEscapedURI(); ... to if (!itself) { String myURI = httpURL.getEscapedURI(); final String adjustedHref = href.endsWith("/") ? href.substring(0, href.length() - 1) : href; final String name = URIUtil.getName(adjustedHref); char[] childURI = (myURI + (myURI.endsWith("/") ? "" : "/") + name).toCharArray(); the problem is that children's hrefs can end with '/' and in this case URIUtil.getName returns empty string. Because of that childURI is the same as myURI (bug!!!)
(In reply to comment #14) > I bumped into the problem as well. 2.1 didn't work for me. > A solution was to change a part of WebdavResource.setWebdavProperties after > > if (!itself) { > String myURI = httpURL.getEscapedURI(); > > ... > > to > > if (!itself) { > String myURI = httpURL.getEscapedURI(); > final String adjustedHref = href.endsWith("/") ? > href.substring(0, href.length() - 1) : href; > final String name = URIUtil.getName(adjustedHref); > char[] childURI = (myURI + (myURI.endsWith("/") ? "" : "/") > + name).toCharArray(); > > the problem is that children's hrefs can end with '/' and in this case > URIUtil.getName returns empty string. Because of that childURI is the same as > myURI (bug!!!) Thanks Igor! Everything works fine now. Also thanks to Robert and Philip. For those who want a fast cut-and-paste solution, simply replace the entire protected void setWebdavProperties(Enumeration responses) method in org.apache.webdav.lib.WebdavResource with the following code: // START: FIX ///////////////////////////////////////////////////// /** * Set WebDAV properties following to the given http URL. * This method is fundamental for getting information of a collection. * * @param responses An enumeration over {@link ResponseEntity} items, one * for each resource for which information was returned via PROPFIND. * * @exception HttpException * @exception IOException The socket error with a server. */ protected void setWebdavProperties(Enumeration responses) throws HttpException, IOException { // Make the resources in the collection empty. childResources.removeAll(); while (responses.hasMoreElements()) { ResponseEntity response = (ResponseEntity) responses.nextElement(); boolean itself = false; String href = response.getHref(); if (!href.startsWith("/")) href = URIUtil.getPath(href); href = decodeMarks(href); /* * Decode URIs to common (unescaped) format for comparison * as HttpClient.URI.setPath() doesn't escape $ and : chars. */ String httpURLPath = httpURL.getPath(); String escapedHref = URIUtil.decode(href); // Normalize them to both have trailing slashes if they differ by one in length. int lenDiff = escapedHref.length() - httpURLPath.length(); int compareLen = 0; if ( lenDiff == -1 && !escapedHref.endsWith("/")) { compareLen = escapedHref.length(); lenDiff = 0; } else if ( lenDiff == 1 && !httpURLPath.endsWith("/")) { compareLen = httpURLPath.length(); lenDiff = 0; } // if they are the same length then compare them. if (lenDiff == 0) { if ((compareLen == 0 && httpURLPath.equals(escapedHref)) || httpURLPath.regionMatches(0, escapedHref, 0, compareLen)) { // escaped href and http path are the same // Set the status code for this resource. if (response.getStatusCode() > 0) setStatusCode(response.getStatusCode()); setExistence(true); itself = true; } } // Get to know each resource. WebdavResource workingResource = null; if (itself) { workingResource = this; } else { workingResource = createWebdavResource(client); workingResource.setDebug(debug); } // clear the current lock set workingResource.setLockDiscovery(null); // Process the resource's properties Enumeration properties = response.getProperties(); while (properties.hasMoreElements()) { Property property = (Property) properties.nextElement(); // ------------------------------ Checking WebDAV properties workingResource.processProperty(property); } String displayName = workingResource.getDisplayName(); if (displayName == null || displayName.trim().equals("")) { displayName = getName(href); } /** BUGGY CODE if (!itself) { String myURI = httpURL.getEscapedURI(); char[] childURI = (myURI + (myURI.endsWith("/") ? "" : "/") + URIUtil.getName(href)).toCharArray(); HttpURL childURL = httpURL instanceof HttpsURL ? new HttpsURL(childURI) : new HttpURL(childURI); childURL.setRawAuthority(httpURL.getRawAuthority()); workingResource.setHttpURL(childURL, NOACTION, defaultDepth); workingResource.setExistence(true); workingResource.setOverwrite(getOverwrite()); } */ /** FIX ********/ if (!itself) { String myURI = httpURL.getEscapedURI(); /** Checks if href contains trailing '/', and if so removes it. This ensures URIUtil.getName does not return an empty String when we don't want it to. See http://issues.apache.org/bugzilla/show_bug.cgi?id=32886 for more information. */ String fixedHref = href.endsWith("/") ? href.substring(0, href.length() - 1) : href; char[] childURI = (myURI + (myURI.endsWith("/") ? "" : "/") + URIUtil.getName(fixedHref)).toCharArray(); HttpURL childURL = httpURL instanceof HttpsURL ? new HttpsURL(childURI) : new HttpURL(childURI); childURL.setRawAuthority(httpURL.getRawAuthority()); workingResource.setHttpURL(childURL, NOACTION, defaultDepth); workingResource.setExistence(true); workingResource.setOverwrite(getOverwrite()); } /**************/ workingResource.setDisplayName(displayName); if (!itself) childResources.addResource(workingResource); } } // END: FIX ///////////////////////////////////////////////////// The code is based on Igor's solution and should work fine. Please post here if you stumble upon any issues the fix causes. In the meantime however, its working perfectly for me. Cheers! Mike N. Christoff
I am still having problem with this solution. I now have deleted folders beeing listed with the listWebdavResources call... (In reply to comment #0) > I have a mature application working with client webdavlib 2.0, with the webdav > server that comes with tomcat 5.0.28. Client webdavlib 2.1 seams to be broken. > Method listWebdavResources() doesn't return child collections, but the parent > collection itself. > > This is the directory structure I tested: > > parent/ > child1/ > child2/ > file1.txt > file2.txt > > > This is my code: > > HttpURL url = new HttpURL("http://localhost:8080/webdav/[some-url]"); > url.setUserinfo("user", "pass"); > WebdavResource wdResource = new WebdavResource(url); > WebdavResource[] webdavList = wdResource.listWebdavResources(); > > System.out.println("Display Name: " + wdResource.getDisplayName()); > WebdavResource[] webdavList = null; > webdavList = wdResource.listWebdavResources(); > System.out.println("Children returned: " + webdavList.length); > > for (int idx = 0; idx < webdavList.length; idx++) { > System.out.println("\t" + webdavList[idx].getDisplayName()); > System.out.println("\t" + webdavList[idx].getHttpURL()); > } > > This is the output: > > Display Name: parent > Children returned: 3 > file1.txt > http://localhost:8080/webdav/parent/file1.txt > child2 > http://localhost:8080/webdav/parent/ > file2.txt > http://localhost:8080/webdav/parent/file2.txt > > The third result is the URL of the parent, with display name "child2"! > So nothing about child1, although it comes from the server (see trace). > And child2 URL is bad, because it shows parent URL. > > In general, I see that collection childs are never shown. > > And this is the http tracing I got. There are two requests involved, the first > using depth 0 and the second using depth 1. > > FIRST REQUEST > =============== > > PROPFIND /webdav/parent HTTP/1.1 > Authorization: Basic anVncmVnbzE6cGFkZW50cm8= > Content-Type: text/xml; charset=utf-8 > User-Agent: Jakarta Commons-HttpClient/2.0final > Host: localhost:8080 > Content-Length: 207 > Depth: 0 > > <?xml version="1.0" encoding="utf-8"?> > <D:propfind xmlns:D="DAV:"> > <D:prop> > <D:displayname/> > <D:getcontentlength/> > <D:getcontenttype/> > <D:resourcetype/> > <D:getlastmodified/> > <D:lockdiscovery/> > </D:prop> > </D:propfind> > > FIRST RESPONSE > ================= > > HTTP/1.1 207 Multi-Estado > Content-Type: text/xml;charset=UTF-8 > Content-Length: 436 > Date: Thu, 30 Dec 2004 09:51:45 GMT > Server: Apache-Coyote/1.1 > > <?xml version="1.0" encoding="utf-8"?> > <multistatus xmlns="DAV:"> > <response> > <href>/webdav/parent/</href> > <propstat> > <prop> > <displayname><![CDATA[parent]]></displayname> > <resourcetype> > <collection/> > </resourcetype> > </prop> > <status>HTTP/1.1 200 OK</status> > </propstat> > <propstat> > <prop> > <getcontentlength/> > <getcontenttype/> > <getlastmodified/> > <lockdiscovery/> > </prop> > <status>HTTP/1.1 404 Not Found</status> > </propstat> > </response> > </multistatus> > > SECOND REQUEST > ================ > > PROPFIND /webdav/parent HTTP/1.1 > Authorization: Basic anVncmVnbzE6cGFkZW50cm8= > Content-Type: text/xml; charset=utf-8 > User-Agent: Jakarta Commons-HttpClient/2.0final > Host: localhost:8080 > Content-Length: 207 > Depth: 1 > > <?xml version="1.0" encoding="utf-8"?> > <D:propfind xmlns:D="DAV:"> > <D:prop> > <D:displayname/> > <D:getcontentlength/> > <D:getcontenttype/> > <D:resourcetype/> > <D:getlastmodified/> > <D:lockdiscovery/> > </D:prop> > </D:propfind> > > SECOND RESPONSE > ================= > > HTTP/1.1 207 Multi-Estado > Content-Type: text/xml;charset=UTF-8 > Content-Length: 2028 > Date: Thu, 30 Dec 2004 09:51:45 GMT > Server: Apache-Coyote/1.1 > > <?xml version="1.0" encoding="utf-8"?> > <multistatus xmlns="DAV:"> > <response> > <href>/webdav/parent/</href> > <propstat> > <prop> > <displayname><![CDATA[parent]]></displayname> > <resourcetype> > <collection/> > </resourcetype> > </prop> > <status>HTTP/1.1 200 OK</status> > </propstat> > <propstat> > <prop> > <getcontentlength/> > <getcontenttype/> > <getlastmodified/> > <lockdiscovery/> > </prop> > <status>HTTP/1.1 404 Not Found</status> > </propstat> > </response> > <response> > <href>/webdav/parent/file2.txt</href> > <propstat> > <prop> > <displayname><![CDATA[file2.txt]]></displayname> > <getcontentlength>10</getcontentlength> > <getcontenttype>text/plain</getcontenttype> > <resourcetype/> > <getlastmodified>Mon, 27 Sep 2004 11:13:07 GMT</getlastmodified> > </prop> > <status>HTTP/1.1 200 OK</status> > </propstat> > <propstat> > <prop> > <lockdiscovery/> > </prop> > <status>HTTP/1.1 404 Not Found</status> > </propstat> > </response> > <response> > <href>/webdav/parent/file1.txt</href> > <propstat> > <prop> > <displayname><![CDATA[file1.txt]]></displayname> > <getcontentlength>10</getcontentlength> > <getcontenttype>text/plain</getcontenttype> > <resourcetype/> > <getlastmodified>Mon, 27 Sep 2004 11:13:07 GMT</getlastmodified> > </prop> > <status>HTTP/1.1 200 OK</status> > </propstat> > <propstat> > <prop> > <lockdiscovery/> > </prop> > <status>HTTP/1.1 404 Not Found</status> > </propstat> > </response> > <response> > <href>/webdav/parent/child2/</href> > <propstat> > <prop> > <displayname><![CDATA[child2]]></displayname> > <resourcetype> > <collection/> > </resourcetype> > </prop> > <status>HTTP/1.1 200 OK</status> > </propstat> > <propstat> > <prop> > <getcontentlength/> > <getcontenttype/> > <getlastmodified/> > <lockdiscovery/> > </prop> > <status>HTTP/1.1 404 Not Found</status> > </propstat> > </response> > <response> > <href>/webdav/parent/child1/</href> > <propstat> > <prop> > <displayname><![CDATA[child1]]></displayname> > <resourcetype> > <collection/> > </resourcetype> > </prop> > <status>HTTP/1.1 200 OK</status> > </propstat> > <propstat> > <prop> > <getcontentlength/> > <getcontenttype/> > <getlastmodified/> > <lockdiscovery/> > </prop> > <status>HTTP/1.1 404 Not Found</status> > </propstat> > </response> > </multistatus> > > As you can see from the second response, all the resources are returned > correctly from the server. (In reply to comment #16) > (In reply to comment #14) > > I bumped into the problem as well. 2.1 didn't work for me. > > A solution was to change a part of WebdavResource.setWebdavProperties after > > > > if (!itself) { > > String myURI = httpURL.getEscapedURI(); > > > > ... > > > > to > > > > if (!itself) { > > String myURI = httpURL.getEscapedURI(); > > final String adjustedHref = href.endsWith("/") ? > > href.substring(0, href.length() - 1) : href; > > final String name = URIUtil.getName(adjustedHref); > > char[] childURI = (myURI + (myURI.endsWith("/") ? "" : "/") > > + name).toCharArray(); > > > > the problem is that children's hrefs can end with '/' and in this case > > URIUtil.getName returns empty string. Because of that childURI is the same as > > myURI (bug!!!) > > > Thanks Igor! Everything works fine now. Also thanks to Robert and Philip. For > those who want a fast cut-and-paste solution, simply replace the entire > > protected void setWebdavProperties(Enumeration responses) > > method in org.apache.webdav.lib.WebdavResource with the following code: > > // START: FIX ///////////////////////////////////////////////////// > /** > * Set WebDAV properties following to the given http URL. > * This method is fundamental for getting information of a collection. > * > * @param responses An enumeration over {@link ResponseEntity} items, one > * for each resource for which information was returned via PROPFIND. > * > * @exception HttpException > * @exception IOException The socket error with a server. > */ > protected void setWebdavProperties(Enumeration responses) > throws HttpException, IOException { > > // Make the resources in the collection empty. > childResources.removeAll(); > while (responses.hasMoreElements()) { > > ResponseEntity response = > (ResponseEntity) responses.nextElement(); > > boolean itself = false; > String href = response.getHref(); > if (!href.startsWith("/")) > href = URIUtil.getPath(href); > href = decodeMarks(href); > > /* > * Decode URIs to common (unescaped) format for comparison > * as HttpClient.URI.setPath() doesn't escape $ and : chars. > */ > String httpURLPath = httpURL.getPath(); > String escapedHref = URIUtil.decode(href); > > // Normalize them to both have trailing slashes if they differ by > one in length. > int lenDiff = escapedHref.length() - httpURLPath.length(); > int compareLen = 0; > > if ( lenDiff == -1 && !escapedHref.endsWith("/")) { > compareLen = escapedHref.length(); > lenDiff = 0; > } > else > if ( lenDiff == 1 && !httpURLPath.endsWith("/")) { > compareLen = httpURLPath.length(); > lenDiff = 0; > } > > // if they are the same length then compare them. > if (lenDiff == 0) { > if ((compareLen == 0 && httpURLPath.equals(escapedHref)) > || httpURLPath.regionMatches(0, escapedHref, 0, compareLen)) > { > // escaped href and http path are the same > // Set the status code for this resource. > if (response.getStatusCode() > 0) > setStatusCode(response.getStatusCode()); > setExistence(true); > itself = true; > } > } > > // Get to know each resource. > WebdavResource workingResource = null; > if (itself) { > workingResource = this; > } > else { > workingResource = createWebdavResource(client); > workingResource.setDebug(debug); > } > > // clear the current lock set > workingResource.setLockDiscovery(null); > > // Process the resource's properties > Enumeration properties = response.getProperties(); > while (properties.hasMoreElements()) { > > Property property = (Property) properties.nextElement(); > > // ------------------------------ Checking WebDAV properties > workingResource.processProperty(property); > } > > String displayName = workingResource.getDisplayName(); > > if (displayName == null || displayName.trim().equals("")) { > displayName = getName(href); > } > > /** BUGGY CODE > if (!itself) { > String myURI = httpURL.getEscapedURI(); > char[] childURI = (myURI + (myURI.endsWith("/") ? "" : "/") > + URIUtil.getName(href)).toCharArray(); > HttpURL childURL = httpURL instanceof HttpsURL > ? new HttpsURL(childURI) > : new HttpURL(childURI); > childURL.setRawAuthority(httpURL.getRawAuthority()); > workingResource.setHttpURL(childURL, NOACTION, defaultDepth); > workingResource.setExistence(true); > workingResource.setOverwrite(getOverwrite()); > } > */ > > /** FIX ********/ > if (!itself) { > String myURI = httpURL.getEscapedURI(); > > /** > Checks if href contains trailing '/', and if so removes it. > This ensures URIUtil.getName does not return an empty > String when we don't want it to. > > See http://issues.apache.org/bugzilla/show_bug.cgi?id=32886 > for more information. > */ > String fixedHref = href.endsWith("/") ? > href.substring(0, href.length() - 1) : href; > > char[] childURI = (myURI + (myURI.endsWith("/") ? "" : "/") > + URIUtil.getName(fixedHref)).toCharArray(); > > HttpURL childURL = httpURL instanceof HttpsURL > ? new HttpsURL(childURI) > : new HttpURL(childURI); > childURL.setRawAuthority(httpURL.getRawAuthority()); > workingResource.setHttpURL(childURL, NOACTION, defaultDepth); > workingResource.setExistence(true); > workingResource.setOverwrite(getOverwrite()); > } > /**************/ > > > workingResource.setDisplayName(displayName); > > if (!itself) > childResources.addResource(workingResource); > } > } > // END: FIX ///////////////////////////////////////////////////// > > The code is based on Igor's solution and should work fine. Please post here if > you stumble upon any issues the fix causes. In the meantime however, its > working perfectly for me. > > Cheers! > > Mike N. Christoff