diff --git a/app/build.gradle b/app/build.gradle
index 691048626..b3e7fc2f8 100644
--- a/app/build.gradle
+++ b/app/build.gradle
@@ -116,8 +116,10 @@ final STETHO_VERSION = '1.5.0'
final TESTING_SUPPORT_VERSION = '1.0.0'
dependencies {
- implementation project(':ical4android')
- implementation project(':dav4android')
+ implementation ":dav4android:"
+ implementation (":ical4android:") {
+ exclude group: 'org.threeten', module: 'threetenbp'
+ }
annotationProcessor "com.google.dagger:dagger-compiler:${DAGGER_VERSION}"
implementation "com.google.dagger:dagger:${DAGGER_VERSION}"
diff --git a/app/src/main/AndroidManifest.xml b/app/src/main/AndroidManifest.xml
index 84028ca9f..382d37a0f 100644
--- a/app/src/main/AndroidManifest.xml
+++ b/app/src/main/AndroidManifest.xml
@@ -5,7 +5,7 @@
package="org.tasks">
-
+
diff --git a/app/src/main/java/org/tasks/caldav/CaldavClient.java b/app/src/main/java/org/tasks/caldav/CaldavClient.java
index a2c290e17..8c42b6cfe 100644
--- a/app/src/main/java/org/tasks/caldav/CaldavClient.java
+++ b/app/src/main/java/org/tasks/caldav/CaldavClient.java
@@ -8,7 +8,7 @@ import static java.util.Arrays.asList;
import at.bitfire.dav4android.BasicDigestAuthHandler;
import at.bitfire.dav4android.DavResource;
-import at.bitfire.dav4android.PropertyCollection;
+import at.bitfire.dav4android.DavResponse;
import at.bitfire.dav4android.XmlUtils;
import at.bitfire.dav4android.exception.DavException;
import at.bitfire.dav4android.exception.HttpException;
@@ -36,13 +36,15 @@ import org.tasks.data.CaldavAccount;
import org.tasks.data.CaldavCalendar;
import org.tasks.security.Encryption;
import org.tasks.ui.DisplayableException;
+import org.xmlpull.v1.XmlPullParserException;
+import org.xmlpull.v1.XmlPullParserFactory;
import org.xmlpull.v1.XmlSerializer;
import timber.log.Timber;
class CaldavClient {
- private final DavResource davResource;
- private HttpUrl httpUrl;
+ private final OkHttpClient httpClient;
+ private final HttpUrl httpUrl;
CaldavClient(CaldavAccount caldavAccount, Encryption encryption) {
this(
@@ -61,7 +63,7 @@ class CaldavClient {
CaldavClient(String url, String username, String password) {
BasicDigestAuthHandler basicDigestAuthHandler =
new BasicDigestAuthHandler(null, username, password);
- OkHttpClient httpClient =
+ httpClient =
new OkHttpClient()
.newBuilder()
.addNetworkInterceptor(basicDigestAuthHandler)
@@ -73,18 +75,18 @@ class CaldavClient {
.build();
URI uri = URI.create(url);
httpUrl = HttpUrl.get(uri);
- davResource = new DavResource(httpClient, httpUrl);
}
- private String tryFindPrincipal() throws DavException, IOException, HttpException {
+ private String tryFindPrincipal() throws DavException, IOException {
for (String link : asList("", "/.well-known/caldav")) {
HttpUrl url = httpUrl.resolve(link);
Timber.d("Checking for principal: %s", url);
- davResource.setLocation(url);
+ DavResource davResource = new DavResource(httpClient, url);
+ DavResponse response = null;
try {
- davResource.propfind(0, CurrentUserPrincipal.NAME);
+ response = davResource.propfind(0, CurrentUserPrincipal.NAME);
} catch (HttpException e) {
- switch (e.getStatus()) {
+ switch (e.getCode()) {
case 405:
Timber.w(e);
break;
@@ -92,22 +94,23 @@ class CaldavClient {
throw e;
}
}
- PropertyCollection properties = davResource.getProperties();
- CurrentUserPrincipal currentUserPrincipal = properties.get(CurrentUserPrincipal.class);
- if (currentUserPrincipal != null) {
- String href = currentUserPrincipal.getHref();
- if (!isEmpty(href)) {
- return href;
+ if (response != null) {
+ CurrentUserPrincipal currentUserPrincipal = response.get(CurrentUserPrincipal.class);
+ if (currentUserPrincipal != null) {
+ String href = currentUserPrincipal.getHref();
+ if (!isEmpty(href)) {
+ return href;
+ }
}
}
}
return null;
}
- private String findHomeset() throws DavException, IOException, HttpException {
- davResource.propfind(0, CalendarHomeSet.NAME);
- PropertyCollection properties = davResource.getProperties();
- CalendarHomeSet calendarHomeSet = properties.get(CalendarHomeSet.class);
+ private String findHomeset(HttpUrl httpUrl) throws DavException, IOException {
+ DavResource davResource = new DavResource(httpClient, httpUrl);
+ DavResponse response = davResource.propfind(0, CalendarHomeSet.NAME);
+ CalendarHomeSet calendarHomeSet = response.get(CalendarHomeSet.class);
if (calendarHomeSet == null) {
throw new DisplayableException(R.string.caldav_home_set_not_found);
}
@@ -122,32 +125,35 @@ class CaldavClient {
return davResource.getLocation().resolve(homeSet).toString();
}
- public Single getHomeSet() {
+ Single getHomeSet() {
return Single.fromCallable(
() -> {
String principal = tryFindPrincipal();
- if (!isEmpty(principal)) {
- davResource.setLocation(httpUrl.resolve(principal));
- }
- return findHomeset();
+ return findHomeset(isEmpty(principal) ? httpUrl : httpUrl.resolve(principal));
})
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
- public List getCalendars() throws IOException, HttpException, DavException {
- davResource.propfind(
- 1, ResourceType.NAME, DisplayName.NAME, SupportedCalendarComponentSet.NAME, GetCTag.NAME);
- List urls = new ArrayList<>();
- for (DavResource member : davResource.getMembers()) {
- PropertyCollection properties = member.getProperties();
- ResourceType resourceType = properties.get(ResourceType.class);
- if (resourceType == null || !resourceType.getTypes().contains(ResourceType.CALENDAR)) {
+ public List getCalendars() throws IOException, DavException {
+ DavResource davResource = new DavResource(httpClient, httpUrl);
+ DavResponse response =
+ davResource.propfind(
+ 1,
+ ResourceType.NAME,
+ DisplayName.NAME,
+ SupportedCalendarComponentSet.NAME,
+ GetCTag.NAME);
+ List urls = new ArrayList<>();
+ for (DavResponse member : response.getMembers()) {
+ ResourceType resourceType = member.get(ResourceType.class);
+ if (resourceType == null
+ || !resourceType.getTypes().contains(ResourceType.Companion.getCALENDAR())) {
Timber.d("%s is not a calendar", member);
continue;
}
SupportedCalendarComponentSet supportedCalendarComponentSet =
- properties.get(SupportedCalendarComponentSet.class);
+ member.get(SupportedCalendarComponentSet.class);
if (supportedCalendarComponentSet == null
|| !supportedCalendarComponentSet.getSupportsTasks()) {
Timber.d("%s does not support tasks", member);
@@ -158,17 +164,17 @@ class CaldavClient {
return urls;
}
- public Completable deleteCollection() {
- return Completable.fromAction(() -> davResource.delete(null))
+ Completable deleteCollection() {
+ return Completable.fromAction(() -> new DavResource(httpClient, httpUrl).delete(null))
.subscribeOn(Schedulers.io())
.observeOn(AndroidSchedulers.mainThread());
}
- public Single makeCollection(String displayName) {
+ Single makeCollection(String displayName) {
return Single.fromCallable(
() -> {
- davResource.setLocation(
- davResource.getLocation().resolve(UUIDHelper.newUUID() + "/"));
+ DavResource davResource =
+ new DavResource(httpClient, httpUrl.resolve(UUIDHelper.newUUID() + "/"));
String mkcolString = getMkcolString(displayName);
davResource.mkCol(mkcolString);
return davResource.getLocation().toString();
@@ -177,9 +183,10 @@ class CaldavClient {
.observeOn(AndroidSchedulers.mainThread());
}
- private String getMkcolString(String displayName) throws IOException {
+ private String getMkcolString(String displayName) throws IOException, XmlPullParserException {
+ XmlPullParserFactory xmlPullParserFactory = XmlPullParserFactory.newInstance();
+ XmlSerializer xml = xmlPullParserFactory.newSerializer();
StringWriter stringWriter = new StringWriter();
- XmlSerializer xml = XmlUtils.newSerializer();
xml.setOutput(stringWriter);
xml.startDocument("UTF-8", null);
xml.setPrefix("", NS_WEBDAV);
@@ -209,4 +216,8 @@ class CaldavClient {
xml.flush();
return stringWriter.toString();
}
+
+ public OkHttpClient getHttpClient() {
+ return httpClient;
+ }
}
diff --git a/app/src/main/java/org/tasks/caldav/CaldavConverter.java b/app/src/main/java/org/tasks/caldav/CaldavConverter.java
index 434d66058..9c0f35705 100644
--- a/app/src/main/java/org/tasks/caldav/CaldavConverter.java
+++ b/app/src/main/java/org/tasks/caldav/CaldavConverter.java
@@ -4,11 +4,9 @@ import static com.todoroo.astrid.data.Task.URGENCY_SPECIFIC_DAY;
import static com.todoroo.astrid.data.Task.URGENCY_SPECIFIC_DAY_TIME;
import static org.tasks.date.DateTimeUtils.newDateTime;
-import at.bitfire.ical4android.InvalidCalendarException;
import com.google.common.base.Strings;
import com.todoroo.astrid.data.Task;
import com.todoroo.astrid.data.Task.Priority;
-import java.io.IOException;
import java.io.StringReader;
import java.text.DateFormat;
import java.text.ParseException;
@@ -94,14 +92,14 @@ public class CaldavConverter {
return remotePriority > 5 ? Math.min(9, remotePriority) : 9;
}
- public static at.bitfire.ical4android.Task toCaldav(CaldavTask caldavTask, Task task) {
+ static at.bitfire.ical4android.Task toCaldav(CaldavTask caldavTask, Task task) {
at.bitfire.ical4android.Task remote = null;
try {
if (!Strings.isNullOrEmpty(caldavTask.getVtodo())) {
remote =
- at.bitfire.ical4android.Task.fromReader(new StringReader(caldavTask.getVtodo())).get(0);
+ at.bitfire.ical4android.Task.Companion.fromReader(new StringReader(caldavTask.getVtodo())).get(0);
}
- } catch (IOException | InvalidCalendarException e) {
+ } catch (Exception e) {
Timber.e(e);
}
if (remote == null) {
diff --git a/app/src/main/java/org/tasks/caldav/CaldavSynchronizer.java b/app/src/main/java/org/tasks/caldav/CaldavSynchronizer.java
index 1ed42759b..ab4daa7f7 100644
--- a/app/src/main/java/org/tasks/caldav/CaldavSynchronizer.java
+++ b/app/src/main/java/org/tasks/caldav/CaldavSynchronizer.java
@@ -3,7 +3,6 @@ package org.tasks.caldav;
import static com.google.common.base.Strings.isNullOrEmpty;
import static com.google.common.collect.Iterables.filter;
import static com.google.common.collect.Iterables.partition;
-import static com.google.common.collect.Iterables.transform;
import static com.google.common.collect.Lists.newArrayList;
import static com.google.common.collect.Lists.transform;
import static com.google.common.collect.Sets.difference;
@@ -13,15 +12,14 @@ import static org.tasks.time.DateTimeUtils.currentTimeMillis;
import android.content.Context;
import at.bitfire.dav4android.DavCalendar;
import at.bitfire.dav4android.DavResource;
-import at.bitfire.dav4android.PropertyCollection;
+import at.bitfire.dav4android.DavResponse;
import at.bitfire.dav4android.exception.DavException;
import at.bitfire.dav4android.exception.HttpException;
import at.bitfire.dav4android.property.CalendarData;
import at.bitfire.dav4android.property.DisplayName;
import at.bitfire.dav4android.property.GetCTag;
import at.bitfire.dav4android.property.GetETag;
-import at.bitfire.ical4android.InvalidCalendarException;
-import at.bitfire.ical4android.iCalendar;
+import at.bitfire.ical4android.ICalendar;
import com.google.common.base.Strings;
import com.google.common.collect.ImmutableSet;
import com.google.common.collect.Iterables;
@@ -61,7 +59,7 @@ import timber.log.Timber;
public class CaldavSynchronizer {
static {
- iCalendar.Companion.setProdId(
+ ICalendar.Companion.setProdId(
new ProdId("+//IDN tasks.org//android-" + BuildConfig.VERSION_CODE + "//EN"));
}
@@ -112,35 +110,35 @@ public class CaldavSynchronizer {
continue;
}
CaldavClient caldavClient = new CaldavClient(account, encryption);
- List resources;
+ List resources;
try {
resources = caldavClient.getCalendars();
- } catch (IOException | DavException | HttpException e) {
+ } catch (IOException | DavException e) {
account.setError(e.getMessage());
caldavDao.update(account);
localBroadcastManager.broadcastRefreshList();
Timber.e(e);
continue;
}
- Set urls = newHashSet(transform(resources, c -> c.getLocation().toString()));
+ Set urls = newHashSet(transform(resources, c -> c.getUrl().toString()));
Timber.d("Found calendars: %s", urls);
for (CaldavCalendar calendar :
caldavDao.findDeletedCalendars(account.getUuid(), newArrayList(urls))) {
taskDeleter.delete(calendar);
}
- for (DavResource resource : resources) {
- String url = resource.getLocation().toString();
- PropertyCollection properties = resource.getProperties();
+ for (DavResponse resource : resources) {
+ String url = resource.getUrl().toString();
+
CaldavCalendar calendar = caldavDao.getCalendarByUrl(account.getUuid(), url);
if (calendar == null) {
calendar = new CaldavCalendar();
- calendar.setName(properties.get(DisplayName.class).getDisplayName());
+ calendar.setName(resource.get(DisplayName.class).getDisplayName());
calendar.setAccount(account.getUuid());
calendar.setUrl(url);
calendar.setUuid(UUIDHelper.newUUID());
calendar.setId(caldavDao.insert(calendar));
}
- sync(calendar, resource);
+ sync(calendar, resource, caldavClient.getHttpClient());
}
account.setError("");
caldavDao.update(account);
@@ -148,15 +146,13 @@ public class CaldavSynchronizer {
}
}
- private void sync(CaldavCalendar caldavCalendar, DavResource resource) {
+ private void sync(CaldavCalendar caldavCalendar, DavResponse resource, OkHttpClient httpClient) {
Timber.d("sync(%s)", caldavCalendar);
- OkHttpClient httpClient = resource.getHttpClient();
- HttpUrl httpUrl = resource.getLocation();
+ HttpUrl httpUrl = resource.getUrl();
try {
pushLocalChanges(caldavCalendar, httpClient, httpUrl);
- PropertyCollection properties = resource.getProperties();
- String remoteName = properties.get(DisplayName.class).getDisplayName();
+ String remoteName = resource.get(DisplayName.class).getDisplayName();
if (!caldavCalendar.getName().equals(remoteName)) {
Timber.d("%s -> %s", caldavCalendar.getName(), remoteName);
caldavCalendar.setName(remoteName);
@@ -164,7 +160,7 @@ public class CaldavSynchronizer {
localBroadcastManager.broadcastRefreshList();
}
- String remoteCtag = properties.get(GetCTag.class).getCTag();
+ String remoteCtag = resource.get(GetCTag.class).getCTag();
String localCtag = caldavCalendar.getCtag();
if (localCtag != null && localCtag.equals(remoteCtag)) {
@@ -174,16 +170,15 @@ public class CaldavSynchronizer {
DavCalendar davCalendar = new DavCalendar(httpClient, httpUrl);
- davCalendar.calendarQuery("VTODO", null, null);
+ List members = davCalendar.calendarQuery("VTODO", null, null).getMembers();
- Set remoteObjects =
- newHashSet(transform(davCalendar.getMembers(), DavResource::fileName));
+ Set remoteObjects = newHashSet(transform(members, DavResponse::fileName));
- Iterable changed =
+ Iterable changed =
filter(
- ImmutableSet.copyOf(davCalendar.getMembers()),
+ ImmutableSet.copyOf(members),
vCard -> {
- GetETag eTag = (GetETag) vCard.getProperties().get(GetETag.NAME);
+ GetETag eTag = vCard.get(GetETag.class);
if (eTag == null || isNullOrEmpty(eTag.getETag())) {
return false;
}
@@ -192,17 +187,17 @@ public class CaldavSynchronizer {
return caldavTask == null || !eTag.getETag().equals(caldavTask.getEtag());
});
- for (List items : partition(changed, 30)) {
+ for (List items : partition(changed, 30)) {
if (items.size() == 1) {
- DavResource vCard = items.get(0);
- PropertyCollection vcardProperties = vCard.getProperties();
- GetETag eTag = (GetETag) vcardProperties.get(GetETag.NAME);
+ DavResponse vCard = items.get(0);
+ GetETag eTag = vCard.get(GetETag.class);
if (eTag == null || isNullOrEmpty(eTag.getETag())) {
throw new DavException(
- "Received CalDAV GET response without ETag for " + vCard.getLocation());
+ "Received CalDAV GET response without ETag for " + vCard.getUrl());
}
- Timber.d("SINGLE %s", vCard.getLocation());
- ResponseBody responseBody = vCard.get("text/calendar");
+ Timber.d("SINGLE %s", vCard.getUrl());
+ DavResponse response = new DavResource(httpClient, vCard.getUrl()).get("text/calendar");
+ ResponseBody responseBody = response.getBody();
Reader reader = null;
try {
reader = responseBody.charStream();
@@ -215,23 +210,21 @@ public class CaldavSynchronizer {
}
} else {
ArrayList urls =
- newArrayList(Iterables.transform(items, DavResource::getLocation));
- davCalendar.multiget(urls);
+ newArrayList(Iterables.transform(items, DavResponse::getUrl));
+ DavResponse response = davCalendar.multiget(urls);
Timber.d("MULTI %s", urls);
- for (DavResource vCard : davCalendar.getMembers()) {
- PropertyCollection vcardProperties = vCard.getProperties();
-
- GetETag eTag = (GetETag) vcardProperties.get(GetETag.NAME);
+ for (DavResponse vCard : response.getMembers()) {
+ GetETag eTag = vCard.get(GetETag.class);
if (eTag == null || isNullOrEmpty(eTag.getETag())) {
throw new DavException(
- "Received CalDAV GET response without ETag for " + vCard.getLocation());
+ "Received CalDAV GET response without ETag for " + vCard.getUrl());
}
- CalendarData calendarData = (CalendarData) vcardProperties.get(CalendarData.NAME);
+ CalendarData calendarData = vCard.get(CalendarData.class);
if (calendarData == null || isNullOrEmpty(calendarData.getICalendar())) {
throw new DavException(
- "Received CalDAV GET response without CalendarData for " + vCard.getLocation());
+ "Received CalDAV GET response without CalendarData for " + vCard.getUrl());
}
processVTodo(
@@ -253,7 +246,7 @@ public class CaldavSynchronizer {
caldavCalendar.setCtag(remoteCtag);
Timber.d("UPDATE %s", caldavCalendar);
caldavDao.update(caldavCalendar);
- } catch (IOException | HttpException | DavException e) {
+ } catch (IOException | DavException e) {
Timber.e(e);
} catch (Exception e) {
Timber.e(e);
@@ -284,7 +277,7 @@ public class CaldavSynchronizer {
remote.delete(null);
}
} catch (HttpException e) {
- if (e.getStatus() != 404) {
+ if (e.getCode() != 404) {
Timber.e(e);
return false;
}
@@ -334,14 +327,14 @@ public class CaldavSynchronizer {
ByteArrayOutputStream os = new ByteArrayOutputStream();
remoteModel.write(os);
byte[] data = os.toByteArray();
- RequestBody requestBody = RequestBody.create(DavCalendar.MIME_ICALENDAR, data);
+ RequestBody requestBody = RequestBody.create(DavCalendar.Companion.getMIME_ICALENDAR(), data);
try {
DavResource remote =
new DavResource(
httpClient, httpUrl.newBuilder().addPathSegment(caldavTask.getObject()).build());
- remote.put(requestBody, null, false);
- GetETag getETag = remote.getProperties().get(GetETag.class);
+ DavResponse response = remote.put(requestBody, null, false);
+ GetETag getETag = response.get(GetETag.class);
if (getETag != null && !isNullOrEmpty(getETag.getETag())) {
caldavTask.setEtag(getETag.getETag());
caldavTask.setVtodo(new String(data));
@@ -357,12 +350,11 @@ public class CaldavSynchronizer {
}
private void processVTodo(
- String fileName, CaldavCalendar caldavCalendar, String eTag, String vtodo)
- throws IOException {
+ String fileName, CaldavCalendar caldavCalendar, String eTag, String vtodo) {
List tasks;
try {
- tasks = at.bitfire.ical4android.Task.fromReader(new StringReader(vtodo));
- } catch (InvalidCalendarException e) {
+ tasks = at.bitfire.ical4android.Task.Companion.fromReader(new StringReader(vtodo));
+ } catch (Exception e) {
Timber.e(e);
return;
}
diff --git a/dav4android b/dav4android
index e00c8fa36..d026e6d7d 160000
--- a/dav4android
+++ b/dav4android
@@ -1 +1 @@
-Subproject commit e00c8fa36990a1a6184fb6c8a7ab6229b3117d42
+Subproject commit d026e6d7dbf4a0fdecc7bda28c9cf581a6a7e405
diff --git a/ical4android b/ical4android
index 4c1ff076c..c615f1173 160000
--- a/ical4android
+++ b/ical4android
@@ -1 +1 @@
-Subproject commit 4c1ff076c12b577e7d8daaf35bcc6f09b80c5554
+Subproject commit c615f117365a0b84734f447c37ca4081bec40456
diff --git a/settings.gradle b/settings.gradle
index f5f47dbc9..a8f498869 100644
--- a/settings.gradle
+++ b/settings.gradle
@@ -1 +1,4 @@
-include 'app', 'ical4android', 'dav4android'
+include 'app'
+
+includeBuild 'dav4android'
+includeBuild 'ical4android'