Skip to content

Commit

Permalink
Merge pull request #37 from rt1shnik/fix_lock
Browse files Browse the repository at this point in the history
Add additional method for interaction with locked resources
  • Loading branch information
guillaume-tgl authored Feb 10, 2020
2 parents 61b4720 + 5c04e35 commit 89f4285
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 8 deletions.
42 changes: 42 additions & 0 deletions src/main/java/com/thegrizzlylabs/sardineandroid/DavResource.java
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@

package com.thegrizzlylabs.sardineandroid;

import com.thegrizzlylabs.sardineandroid.model.Lockdiscovery;
import com.thegrizzlylabs.sardineandroid.model.Propstat;
import com.thegrizzlylabs.sardineandroid.model.Resourcetype;
import com.thegrizzlylabs.sardineandroid.model.Response;
import com.thegrizzlylabs.sardineandroid.model.Supportedlock;
import com.thegrizzlylabs.sardineandroid.util.SardineUtil;

import org.w3c.dom.Element;
Expand Down Expand Up @@ -80,6 +82,8 @@ private class DavProperties {
final Long contentLength;
//final List<QName> supportedReports;
final Map<QName, String> customProps;
final Lockdiscovery lockDiscovery;
final Supportedlock supportedLock;

DavProperties(Date creation, Date modified, String contentType,
Long contentLength, String etag, String displayName, List<QName> resourceTypes,
Expand All @@ -94,6 +98,8 @@ private class DavProperties {
this.contentLanguage = contentLanguage;
//this.supportedReports = supportedReports;
this.customProps = customProps;
this.lockDiscovery = null;
this.supportedLock = null;
}

DavProperties(Response response) {
Expand All @@ -107,6 +113,8 @@ private class DavProperties {
this.contentLanguage = getContentLanguage(response);
//this.supportedReports = getSupportedReports(response);
this.customProps = getCustomProps(response);
this.lockDiscovery = getLockDiscovery(response);
this.supportedLock = getSupportedLock(response);
}
}

Expand Down Expand Up @@ -414,6 +422,32 @@ private Map<QName, String> getCustomProps(Response response) {
return customPropsMap;
}

private Lockdiscovery getLockDiscovery(Response response) {
List<Propstat> list = response.getPropstat();
if (list.isEmpty()) {
return null;
}
for (Propstat propstat : list) {
if (propstat.getProp() != null) {
return propstat.getProp().getLockdiscovery();
}
}
return null;
}

private Supportedlock getSupportedLock(Response response) {
List<Propstat> list = response.getPropstat();
if (list.isEmpty()) {
return null;
}
for (Propstat propstat : list) {
if (propstat.getProp() != null) {
return propstat.getProp().getSupportedlock();
}
}
return null;
}

/**
* @return Status code (or 200 if not present, or -1 if malformed)
*/
Expand Down Expand Up @@ -513,6 +547,14 @@ public Map<QName, String> getCustomPropsNS() {
return this.props.customProps;
}

public Lockdiscovery getLockDiscovery() {
return this.props.lockDiscovery;
}

public Supportedlock getSupportedlock() {
return this.props.supportedLock;
}

/**
* @return URI of the resource.
*/
Expand Down
45 changes: 45 additions & 0 deletions src/main/java/com/thegrizzlylabs/sardineandroid/Sardine.java
Original file line number Diff line number Diff line change
Expand Up @@ -280,6 +280,20 @@ public interface Sardine
*/
void put(String url, File localFile, String contentType, boolean expectContinue) throws IOException;


/**
* Uses <code>PUT</code> to upload file to a server with specific contentType.
* Repeatable on authentication failure.
*
* @param url Path to the resource including protocol and hostname
* @param localFile local file to send
* @param contentType MIME type to add to the HTTP request header
* @param expectContinue Enable <code>Expect: continue</code> header for <code>PUT</code> requests.
* @param lockToken A lock token is a type of state token that identifies a particular lock.
* @throws IOException I/O error or HTTP response validation failure
*/
void put(String url, File localFile, String contentType, boolean expectContinue, String lockToken) throws IOException;

/**
* Delete a resource using HTTP <code>DELETE</code> at the specified url
*
Expand Down Expand Up @@ -315,6 +329,17 @@ public interface Sardine
*/
void move(String sourceUrl, String destinationUrl, boolean overwrite) throws IOException;

/**
* Move a url to from source to destination using WebDAV <code>MOVE</code>.
*
* @param sourceUrl Path to the resource including protocol and hostname
* @param destinationUrl Path to the resource including protocol and hostname
* @param overwrite {@code true} to overwrite if the destination exists, {@code false} otherwise.
* @param lockToken A lock token is a type of state token that identifies a particular lock.
* @throws IOException I/O error or HTTP response validation failure
*/
void move(String sourceUrl, String destinationUrl, boolean overwrite, String lockToken) throws IOException;

/**
* Copy a url from source to destination using WebDAV <code>COPY</code>. Assumes overwrite.
*
Expand Down Expand Up @@ -362,6 +387,26 @@ public interface Sardine
*/
String lock(String url) throws IOException;

/**
* <p>
* Put an exclusive write lock on this resource. A write lock must prevent a principal without
* the lock from successfully executing a PUT, POST, PROPPATCH, LOCK, UNLOCK, MOVE, DELETE, or MKCOL
* on the locked resource. All other current methods, GET in particular, function
* independently of the lock.
* </p>
* A WebDAV compliant server is not required to support locking in any form. If the server does support
* locking it may choose to support any combination of exclusive and shared locks for any access types.
*
* @param url Path to the resource including protocol and hostname
* @param timeout Timeout is measured in seconds remaining until lock expiration.
* @return The lock token to unlock this resource. A lock token is a type of state token, represented
* as a URI, which identifies a particular lock. A lock token is returned by every successful
* <code>LOCK</code> operation in the lockdiscovery property in the response body, and can also be found through
* lock discovery on a resource.
* @throws IOException I/O error or HTTP response validation failure
*/
String lock(String url, int timeout) throws IOException;

/**
* A LOCK request with no request body is a "LOCK refresh" request. It's purpose is to restart all timers
* associated with a lock. The request MUST include an "If" header that contains the lock tokens of the
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
package com.thegrizzlylabs.sardineandroid.impl;

import android.text.TextUtils;

import com.thegrizzlylabs.sardineandroid.DavAce;
import com.thegrizzlylabs.sardineandroid.DavAcl;
import com.thegrizzlylabs.sardineandroid.DavPrincipal;
Expand Down Expand Up @@ -302,12 +304,20 @@ public void put(String url, File localFile, String contentType) throws IOExcepti

@Override
public void put(String url, File localFile, String contentType, boolean expectContinue) throws IOException {
put(url, localFile, contentType, expectContinue, null);
}

@Override
public void put(String url, File localFile, String contentType, boolean expectContinue, String lockToken) throws IOException {
MediaType mediaType = contentType == null ? null : MediaType.parse(contentType);
RequestBody requestBody = RequestBody.create(mediaType, localFile);
Headers.Builder headersBuilder = new Headers.Builder();
if (expectContinue) {
headersBuilder.add("Expect", "100-Continue");
}
if (!TextUtils.isEmpty(lockToken)) {
addLockTokenToHeaders(headersBuilder, url, lockToken);
}
put(url, requestBody, headersBuilder.build());
}

Expand Down Expand Up @@ -349,15 +359,31 @@ public void move(String sourceUrl, String destinationUrl) throws IOException {

@Override
public void move(String sourceUrl, String destinationUrl, boolean overwrite) throws IOException {
Request request = new Request.Builder()
move(sourceUrl, destinationUrl, overwrite, null);
}

@Override
public void move(String sourceUrl, String destinationUrl, boolean overwrite, String lockToken) throws IOException {
Request.Builder builder = new Request.Builder()
.url(sourceUrl)
.method("MOVE", null)
.header("DESTINATION", URI.create(destinationUrl).toASCIIString())
.header("OVERWRITE", overwrite ? "T" : "F")
.build();
.method("MOVE", null);

Headers.Builder headersBuilder = new Headers.Builder();
headersBuilder.add("DESTINATION", URI.create(destinationUrl).toASCIIString());
headersBuilder.add("OVERWRITE", overwrite ? "T" : "F");

if (lockToken != null) {
addLockTokenToHeaders(headersBuilder, destinationUrl, lockToken);
}
builder.headers(headersBuilder.build());
Request request = builder.build();
execute(request);
}

private void addLockTokenToHeaders(Headers.Builder headersBuilder, String destinationUrl, String lockToken) {
headersBuilder.add("If", "<" + destinationUrl + "> (<" + lockToken + ">)");
}

@Override
public void copy(String sourceUrl, String destinationUrl) throws IOException {
copy(sourceUrl, destinationUrl, true);
Expand Down Expand Up @@ -387,6 +413,11 @@ public boolean exists(String url) throws IOException {

@Override
public String lock(String url) throws IOException {
return lock(url, 0);
}

@Override
public String lock(String url, int timeout) throws IOException {
Lockinfo body = new Lockinfo();
Lockscope scopeType = new Lockscope();
scopeType.setExclusive(new Exclusive());
Expand All @@ -397,10 +428,13 @@ public String lock(String url) throws IOException {

RequestBody requestBody = RequestBody.create(MediaType.parse("text/xml"), SardineUtil.toXml(body));

Request request = new Request.Builder()
Request.Builder builder = new Request.Builder()
.url(url)
.method("LOCK", requestBody)
.build();
.method("LOCK", requestBody);
if (timeout > 0) {
builder.header("Timeout", "Second-" + timeout);
}
Request request = builder.build();
return execute(request, new LockResponseHandler());
}

Expand Down

0 comments on commit 89f4285

Please sign in to comment.