From 2030cca77843e30057c2d551b4284fb1d74ff133 Mon Sep 17 00:00:00 2001 From: arusin Date: Wed, 28 Aug 2013 03:50:11 -0700 Subject: [PATCH 1/4] Allow non-allprop requests (against possible inefficiencies); retrieve contentlength properly --- src/de/aflx/sardine/DavResource.java | 23 +++++++++++++++++------ src/de/aflx/sardine/Sardine.java | 13 +++++++++++++ src/de/aflx/sardine/impl/SardineImpl.java | 19 ++++++++++++++++--- src/de/aflx/sardine/model/Prop.java | 20 +++++++++++++++----- 4 files changed, 61 insertions(+), 14 deletions(-) diff --git a/src/de/aflx/sardine/DavResource.java b/src/de/aflx/sardine/DavResource.java index 6eba99f..2515f2f 100644 --- a/src/de/aflx/sardine/DavResource.java +++ b/src/de/aflx/sardine/DavResource.java @@ -215,13 +215,24 @@ private String getContentType(Response response) */ private long getContentLength(Response response) { -// Propstat list = response.getPropstat(); -// if(list.equals("") || null == list) { -// return null; -// } -// Getcontentlength gcl = list.getProp().ge; + + Propstat list = response.getPropstat(); + if(list.equals("") || null == list) { + return DEFAULT_CONTENT_LENGTH; + } - return -1; + String gcl = list.getProp().getGetcontentlength(); + if ((gcl != null) && (!gcl.isEmpty())) + { + try + { + return Long.parseLong(gcl); + } catch (NumberFormatException e) + { + log.warn(String.format("Failed to parse content length %s", gcl)); + } + } + return DEFAULT_CONTENT_LENGTH; /*List list = response.getPropstat(); if (list.isEmpty()) { return DEFAULT_CONTENT_LENGTH; diff --git a/src/de/aflx/sardine/Sardine.java b/src/de/aflx/sardine/Sardine.java index 93e9757..d6a25ae 100644 --- a/src/de/aflx/sardine/Sardine.java +++ b/src/de/aflx/sardine/Sardine.java @@ -61,6 +61,19 @@ public interface Sardine */ List list(String url, int depth) throws IOException; + /** + * Gets a directory listing using WebDAV PROPFIND. + * + * @param url Path to the resource including protocol and hostname + * @param depth The depth to look at (use 0 for single ressource, 1 for directory listing) + * @param allProp If allprop should be used, which can be inefficient sometimes; + * warning: no allprop does not retrieve custom props, just the basic ones + * @return List of resources for this URI including the parent resource itself + * @throws IOException I/O error or HTTP response validation failure + */ + List list(String url, int depth, boolean allProp) + throws IOException; + /** * @see #patch(String, java.util.Map, java.util.List) */ diff --git a/src/de/aflx/sardine/impl/SardineImpl.java b/src/de/aflx/sardine/impl/SardineImpl.java index 4a3d273..87042c2 100644 --- a/src/de/aflx/sardine/impl/SardineImpl.java +++ b/src/de/aflx/sardine/impl/SardineImpl.java @@ -101,6 +101,8 @@ import de.aflx.sardine.model.Lockscope; import de.aflx.sardine.model.Locktype; import de.aflx.sardine.model.Multistatus; +import de.aflx.sardine.model.ObjectFactory; +import de.aflx.sardine.model.Prop; import de.aflx.sardine.model.Propfind; import de.aflx.sardine.model.Response; import de.aflx.sardine.model.Write; @@ -390,14 +392,25 @@ public List list(String url) throws IOException { * * @see de.aflx.sardine.Sardine#list(java.lang.String) */ - public List list(String url, int depth) throws IOException { + @Override + public List list(String url, int depth) throws IOException + { + return list(url, depth, true); + } + + @Override + public List list(String url, int depth, boolean allProp) throws IOException + { log.warn("list"); HttpPropFind entity = new HttpPropFind(url); entity.setDepth(Integer.toString(depth)); Propfind body = new Propfind(); - body.setAllprop(new Allprop()); + if (allProp) + entity.setEntity(new StringEntity(" ", UTF_8)); + else + entity.setEntity(new StringEntity(" ", UTF_8)); + // entity.setEntity(new StringEntity(SardineUtil.toXml(body), UTF_8)); - entity.setEntity(new StringEntity(" ", UTF_8)); Multistatus multistatus = this.execute(entity, new MultiStatusResponseHandler()); List responses = multistatus.getResponse(); diff --git a/src/de/aflx/sardine/model/Prop.java b/src/de/aflx/sardine/model/Prop.java index 102e068..3ead6fb 100644 --- a/src/de/aflx/sardine/model/Prop.java +++ b/src/de/aflx/sardine/model/Prop.java @@ -57,14 +57,16 @@ public class Prop { @Element private Resourcetype resourcetype; - @Element + @Element (required = false) private String creationdate; - @Element + @Element (required = false) private String getlastmodified; - @Element + @Element (required = false) private String getetag; @Element (required = false) private String getcontenttype; + @Element (required = false) + private String getcontentlength; public Resourcetype getResourcetype() { return resourcetype; @@ -85,9 +87,17 @@ public String getGetetag() { public String getGetcontenttype() { return getcontenttype; } - - /*protected Creationdate creationdate; + public String getGetcontentlength() { + return getcontentlength; + } + + public void setGetcontentlength(String getcontentlength) { + this.getcontentlength = getcontentlength; + } + + + /*protected Creationdate creationdate; protected Displayname displayname; protected Getcontentlanguage getcontentlanguage; protected Getcontentlength getcontentlength; From 8b56450e985f4096aafcc158df4cc7811c0a5757 Mon Sep 17 00:00:00 2001 From: arusin Date: Wed, 28 Aug 2013 03:53:45 -0700 Subject: [PATCH 2/4] Allow non-allprop requests (against possible inefficiencies); retrieve contentlength properly - slight cleanup --- src/de/aflx/sardine/impl/SardineImpl.java | 6 +----- src/de/aflx/sardine/model/Prop.java | 4 ---- 2 files changed, 1 insertion(+), 9 deletions(-) diff --git a/src/de/aflx/sardine/impl/SardineImpl.java b/src/de/aflx/sardine/impl/SardineImpl.java index 87042c2..8da62c4 100644 --- a/src/de/aflx/sardine/impl/SardineImpl.java +++ b/src/de/aflx/sardine/impl/SardineImpl.java @@ -95,15 +95,11 @@ import de.aflx.sardine.impl.methods.HttpMove; import de.aflx.sardine.impl.methods.HttpPropFind; import de.aflx.sardine.impl.methods.HttpUnlock; -import de.aflx.sardine.model.Allprop; import de.aflx.sardine.model.Exclusive; import de.aflx.sardine.model.Lockinfo; import de.aflx.sardine.model.Lockscope; import de.aflx.sardine.model.Locktype; import de.aflx.sardine.model.Multistatus; -import de.aflx.sardine.model.ObjectFactory; -import de.aflx.sardine.model.Prop; -import de.aflx.sardine.model.Propfind; import de.aflx.sardine.model.Response; import de.aflx.sardine.model.Write; import de.aflx.sardine.util.Logger; @@ -404,7 +400,7 @@ public List list(String url, int depth, boolean allProp) throws IOE log.warn("list"); HttpPropFind entity = new HttpPropFind(url); entity.setDepth(Integer.toString(depth)); - Propfind body = new Propfind(); +// Propfind body = new Propfind(); if (allProp) entity.setEntity(new StringEntity(" ", UTF_8)); else diff --git a/src/de/aflx/sardine/model/Prop.java b/src/de/aflx/sardine/model/Prop.java index 3ead6fb..26c02a7 100644 --- a/src/de/aflx/sardine/model/Prop.java +++ b/src/de/aflx/sardine/model/Prop.java @@ -92,10 +92,6 @@ public String getGetcontentlength() { return getcontentlength; } - public void setGetcontentlength(String getcontentlength) { - this.getcontentlength = getcontentlength; - } - /*protected Creationdate creationdate; protected Displayname displayname; From 2ad3ef8a41be3fd33134a03850f6a5390dbe5b83 Mon Sep 17 00:00:00 2001 From: arusin Date: Wed, 28 Aug 2013 05:45:58 -0700 Subject: [PATCH 3/4] Add a put() method with length --- src/de/aflx/sardine/Sardine.java | 16 ++++++++ src/de/aflx/sardine/impl/SardineImpl.java | 50 +++++++++++++++++++---- 2 files changed, 58 insertions(+), 8 deletions(-) diff --git a/src/de/aflx/sardine/Sardine.java b/src/de/aflx/sardine/Sardine.java index d6a25ae..1f76845 100644 --- a/src/de/aflx/sardine/Sardine.java +++ b/src/de/aflx/sardine/Sardine.java @@ -3,6 +3,8 @@ //import javax.xml.namespace.QName; import de.aflx.sardine.impl.io.ConsumingInputStream; import de.aflx.sardine.util.QName; + +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.List; @@ -183,6 +185,19 @@ List list(String url, int depth, boolean allProp) */ void put(String url, InputStream dataStream, Map headers) throws IOException; + /** + * Uses PUT to send data to a server with a specific content + * type header. Not repeatable on authentication failure. + * + * @param url Path to the resource including protocol and hostname + * @param dataStream Input source + * @param contentType MIME type to add to the HTTP request header + * @param length length of the stream + * @throws IOException I/O error or HTTP response validation failure + */ + void put(String url, File dataStream, int length, String contentType) + throws IOException; + /** * Delete a resource using HTTP DELETE at the specified url * @@ -287,4 +302,5 @@ List list(String url, int depth, boolean allProp) */ void disablePreemptiveAuthentication(); + } \ No newline at end of file diff --git a/src/de/aflx/sardine/impl/SardineImpl.java b/src/de/aflx/sardine/impl/SardineImpl.java index 8da62c4..8a652a4 100644 --- a/src/de/aflx/sardine/impl/SardineImpl.java +++ b/src/de/aflx/sardine/impl/SardineImpl.java @@ -16,6 +16,7 @@ package de.aflx.sardine.impl; +import java.io.File; import java.io.IOException; import java.io.InputStream; import java.net.ProxySelector; @@ -26,10 +27,7 @@ import java.util.List; import java.util.Map; -import de.aflx.sardine.util.QName; - import org.apache.http.HttpEntity; -//import org.apache.http.HttpHeaders; import org.apache.http.HttpException; import org.apache.http.HttpHost; import org.apache.http.HttpRequest; @@ -42,7 +40,6 @@ import org.apache.http.auth.Credentials; import org.apache.http.auth.NTCredentials; import org.apache.http.auth.UsernamePasswordCredentials; -//import org.apache.http.client.AuthCache; import org.apache.http.client.CredentialsProvider; import org.apache.http.client.HttpResponseException; import org.apache.http.client.ResponseHandler; @@ -53,8 +50,6 @@ import org.apache.http.client.methods.HttpRequestBase; import org.apache.http.client.params.AuthPolicy; import org.apache.http.client.protocol.ClientContext; -//import org.apache.http.client.protocol.RequestAcceptEncoding; -//import org.apache.http.client.protocol.ResponseContentEncoding; import org.apache.http.conn.ClientConnectionManager; import org.apache.http.conn.routing.HttpRoutePlanner; import org.apache.http.conn.scheme.PlainSocketFactory; @@ -62,13 +57,12 @@ import org.apache.http.conn.scheme.SchemeRegistry; import org.apache.http.conn.ssl.SSLSocketFactory; import org.apache.http.entity.ByteArrayEntity; +import org.apache.http.entity.FileEntity; import org.apache.http.entity.InputStreamEntity; import org.apache.http.entity.StringEntity; import org.apache.http.impl.auth.BasicScheme; import org.apache.http.impl.client.AbstractHttpClient; -//import org.apache.http.impl.client.BasicAuthCache; import org.apache.http.impl.client.DefaultHttpClient; -//import org.apache.http.impl.client.DefaultRedirectStrategy; import org.apache.http.impl.conn.ProxySelectorRoutePlanner; import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager; import org.apache.http.params.BasicHttpParams; @@ -103,7 +97,14 @@ import de.aflx.sardine.model.Response; import de.aflx.sardine.model.Write; import de.aflx.sardine.util.Logger; +import de.aflx.sardine.util.QName; import de.aflx.sardine.util.SardineUtil; +//import org.apache.http.HttpHeaders; +//import org.apache.http.client.AuthCache; +//import org.apache.http.client.protocol.RequestAcceptEncoding; +//import org.apache.http.client.protocol.ResponseContentEncoding; +//import org.apache.http.impl.client.BasicAuthCache; +//import org.apache.http.impl.client.DefaultRedirectStrategy; /** * Implementation of the Sardine interface. This is where the meat of the @@ -697,6 +698,39 @@ public void put(String url, HttpEntity entity, Map headers) } } + @Override + public void put(String url, File dataStream, int length, String contentType) + throws IOException { + HttpPut put = new HttpPut(url); + FileEntity entity = new FileEntity(dataStream, contentType); + + put.setEntity(entity); + Map headers = new HashMap(); + if (contentType != null) { + headers.put("Content-Type", contentType); + } + /*for (String header : headers.keySet()) { + put.addHeader(header, headers.get(header)); + }*/ + if (!put.containsHeader("Content-Type")) { + put.addHeader("Content-Type", HTTP.DEFAULT_CONTENT_TYPE); + } + try { + this.execute(put, new VoidResponseHandler()); + } catch (HttpResponseException e) { + if (e.getStatusCode() == HttpStatus.SC_EXPECTATION_FAILED) { + // Retry with the Expect header removed + put.removeHeaders(HTTP.EXPECT_DIRECTIVE); + if (entity.isRepeatable()) { + this.execute(put, new VoidResponseHandler()); + return; + } + } + + throw e; + } + } + /** * (non-Javadoc) * From a53ab5787a8bbcd4291e32746fdc23278bf60ddd Mon Sep 17 00:00:00 2001 From: arusin Date: Mon, 23 Sep 2013 08:55:05 -0700 Subject: [PATCH 4/4] More reasonable connection timeout --- src/de/aflx/sardine/impl/SardineImpl.java | 1 + 1 file changed, 1 insertion(+) diff --git a/src/de/aflx/sardine/impl/SardineImpl.java b/src/de/aflx/sardine/impl/SardineImpl.java index 8a652a4..4bdbc3d 100644 --- a/src/de/aflx/sardine/impl/SardineImpl.java +++ b/src/de/aflx/sardine/impl/SardineImpl.java @@ -866,6 +866,7 @@ protected HttpParams createDefaultHttpParams() { HttpConnectionParams.setTcpNoDelay(params, true); HttpConnectionParams.setSocketBufferSize(params, 8192); + HttpConnectionParams.setConnectionTimeout(params, 10*1000); //10 seconds return params; }