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 bu...@apache.org on 2006/10/06 14:26:50 UTC

DO NOT REPLY [Bug 32886] - client webdav lib doesn't return child collections using listwebdavresources

DO NOT REPLY TO THIS EMAIL, BUT PLEASE POST YOUR BUG�
RELATED COMMENTS THROUGH THE WEB INTERFACE AVAILABLE AT
<http://issues.apache.org/bugzilla/show_bug.cgi?id=32886>.
ANY REPLY MADE TO THIS MESSAGE WILL NOT BE COLLECTED AND�
INSERTED IN THE BUG DATABASE.

http://issues.apache.org/bugzilla/show_bug.cgi?id=32886





------- Additional Comments From prileva@yahoo.com  2006-10-06 05:26 -------
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



-- 
Configure bugmail: http://issues.apache.org/bugzilla/userprefs.cgi?tab=email
------- You are receiving this mail because: -------
You are the assignee for the bug, or are watching the assignee.

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