1
0
mirror of https://github.com/etesync/android synced 2024-11-23 00:18:19 +00:00

Refactoring

* VEvent: don't set LAST-MODIFIED to sync time (should be last modification time which is not available)
* ignore 403 Forbidden when uploading (can happen on certain scheduling conditions)
This commit is contained in:
Ricki Hirner 2015-08-10 00:33:26 +02:00
parent fc1874af85
commit faeb3b7dd0
6 changed files with 46 additions and 23 deletions

View File

@ -293,8 +293,6 @@ public class Event extends iCalendar {
event.getProperties().add(forPublic ? Clazz.PUBLIC : Clazz.PRIVATE); event.getProperties().add(forPublic ? Clazz.PUBLIC : Clazz.PRIVATE);
event.getAlarms().addAll(alarms); event.getAlarms().addAll(alarms);
props.add(new LastModified());
return event; return event;
} }

View File

@ -425,7 +425,8 @@ public class LocalCalendar extends LocalCollection<Event> {
// availability // availability
e.opaque = values.getAsInteger(Events.AVAILABILITY) != Events.AVAILABILITY_FREE; e.opaque = values.getAsInteger(Events.AVAILABILITY) != Events.AVAILABILITY_FREE;
// set ORGANIZER // set ORGANIZER if there's attendee data
if (values.getAsInteger(Events.HAS_ATTENDEE_DATA) != 0)
try { try {
e.organizer = new Organizer(new URI("mailto", values.getAsString(Events.ORGANIZER), null)); e.organizer = new Organizer(new URI("mailto", values.getAsString(Events.ORGANIZER), null));
} catch (URISyntaxException ex) { } catch (URISyntaxException ex) {
@ -553,8 +554,8 @@ public class LocalCalendar extends LocalCollection<Event> {
.withValue(entryColumnETag(), event.getETag()) .withValue(entryColumnETag(), event.getETag())
.withValue(entryColumnUID(), event.getUid()); .withValue(entryColumnUID(), event.getUid());
} else { } else {
// event is an exception
builder.withValue(Events.ORIGINAL_SYNC_ID, event.getName()); builder.withValue(Events.ORIGINAL_SYNC_ID, event.getName());
// ORIGINAL_INSTANCE_TIME and ORIGINAL_ALL_DAY is set in buildExceptions. // ORIGINAL_INSTANCE_TIME and ORIGINAL_ALL_DAY is set in buildExceptions.
// It's not possible to use only the RECURRENCE-ID to calculate // It's not possible to use only the RECURRENCE-ID to calculate
// ORIGINAL_INSTANCE_TIME and ORIGINAL_ALL_DAY because iCloud sends DATE-TIME // ORIGINAL_INSTANCE_TIME and ORIGINAL_ALL_DAY because iCloud sends DATE-TIME
@ -616,7 +617,6 @@ public class LocalCalendar extends LocalCollection<Event> {
builder.withValue(Events.ORGANIZER, email != null ? email : uri.toString()); builder.withValue(Events.ORGANIZER, email != null ? email : uri.toString());
} }
//Status status = event.getStatus();
if (event.status!= null) { if (event.status!= null) {
int statusCode = Events.STATUS_TENTATIVE; int statusCode = Events.STATUS_TENTATIVE;
if (event.status == Status.VEVENT_CONFIRMED) if (event.status == Status.VEVENT_CONFIRMED)
@ -639,15 +639,15 @@ public class LocalCalendar extends LocalCollection<Event> {
protected void addDataRows(Resource resource, long localID, int backrefIdx) { protected void addDataRows(Resource resource, long localID, int backrefIdx) {
final Event event = (Event)resource; final Event event = (Event)resource;
// add exceptions
for (Event exception : event.getExceptions())
pendingOperations.add(buildException(newDataInsertBuilder(Events.CONTENT_URI, Events.ORIGINAL_ID, localID, backrefIdx), event, exception).build());
// add attendees // add attendees
for (Attendee attendee : event.getAttendees()) for (Attendee attendee : event.getAttendees())
pendingOperations.add(buildAttendee(newDataInsertBuilder(Attendees.CONTENT_URI, Attendees.EVENT_ID, localID, backrefIdx), attendee).build()); pendingOperations.add(buildAttendee(newDataInsertBuilder(Attendees.CONTENT_URI, Attendees.EVENT_ID, localID, backrefIdx), attendee).build());
// add reminders // add reminders
for (VAlarm alarm : event.getAlarms()) for (VAlarm alarm : event.getAlarms())
pendingOperations.add(buildReminder(newDataInsertBuilder(Reminders.CONTENT_URI, Reminders.EVENT_ID, localID, backrefIdx), alarm).build()); pendingOperations.add(buildReminder(newDataInsertBuilder(Reminders.CONTENT_URI, Reminders.EVENT_ID, localID, backrefIdx), alarm).build());
// add exceptions
for (Event exception : event.getExceptions())
pendingOperations.add(buildException(newDataInsertBuilder(Events.CONTENT_URI, Events.ORIGINAL_ID, localID, backrefIdx), event, exception).build());
} }
@Override @Override
@ -668,7 +668,6 @@ public class LocalCalendar extends LocalCollection<Event> {
protected Builder buildException(Builder builder, Event master, Event exception) { protected Builder buildException(Builder builder, Event master, Event exception) {
buildEntry(builder, exception, false); buildEntry(builder, exception, false);
builder.withValue(Events.ORIGINAL_SYNC_ID, exception.getName());
final boolean originalAllDay = master.isAllDay(); final boolean originalAllDay = master.isAllDay();
@ -685,12 +684,16 @@ public class LocalCalendar extends LocalCollection<Event> {
builder.withValue(Events.ORIGINAL_INSTANCE_TIME, date.getTime()); builder.withValue(Events.ORIGINAL_INSTANCE_TIME, date.getTime());
builder.withValue(Events.ORIGINAL_ALL_DAY, originalAllDay ? 1 : 0); builder.withValue(Events.ORIGINAL_ALL_DAY, originalAllDay ? 1 : 0);
/* TODO reminders and attendees for exceptions are currently not built because
* there's no backref index available */
return builder; return builder;
} }
@SuppressLint("InlinedApi") @SuppressLint("InlinedApi")
protected Builder buildAttendee(Builder builder, Attendee attendee) { protected Builder buildAttendee(Builder builder, Attendee attendee) {
final Uri member = Uri.parse(attendee.getValue()); final URI member = attendee.getCalAddress();
if ("mailto".equalsIgnoreCase(member.getScheme())) if ("mailto".equalsIgnoreCase(member.getScheme()))
// attendee identified by email // attendee identified by email
builder = builder.withValue(Attendees.ATTENDEE_EMAIL, member.getSchemeSpecificPart()); builder = builder.withValue(Attendees.ATTENDEE_EMAIL, member.getSchemeSpecificPart());
@ -760,7 +763,6 @@ public class LocalCalendar extends LocalCollection<Event> {
} }
Log.d(TAG, "Adding alarm " + minutes + " minutes before"); Log.d(TAG, "Adding alarm " + minutes + " minutes before");
return builder return builder
.withValue(Reminders.METHOD, Reminders.METHOD_ALERT) .withValue(Reminders.METHOD, Reminders.METHOD_ALERT)
.withValue(Reminders.MINUTES, minutes); .withValue(Reminders.MINUTES, minutes);

View File

@ -23,6 +23,7 @@ import at.bitfire.davdroid.resource.Resource;
import at.bitfire.davdroid.resource.WebDavCollection; import at.bitfire.davdroid.resource.WebDavCollection;
import at.bitfire.davdroid.webdav.ConflictException; import at.bitfire.davdroid.webdav.ConflictException;
import at.bitfire.davdroid.webdav.DavException; import at.bitfire.davdroid.webdav.DavException;
import at.bitfire.davdroid.webdav.ForbiddenException;
import at.bitfire.davdroid.webdav.HttpException; import at.bitfire.davdroid.webdav.HttpException;
import at.bitfire.davdroid.webdav.NotFoundException; import at.bitfire.davdroid.webdav.NotFoundException;
import at.bitfire.davdroid.webdav.PreconditionFailedException; import at.bitfire.davdroid.webdav.PreconditionFailedException;
@ -119,11 +120,10 @@ public class SyncManager {
remote.delete(res); remote.delete(res);
} catch(NotFoundException e) { } catch(NotFoundException e) {
Log.i(TAG, "Locally-deleted resource has already been removed from server"); Log.i(TAG, "Locally-deleted resource has already been removed from server");
} catch(PreconditionFailedException e) { } catch(PreconditionFailedException|ConflictException e) {
Log.i(TAG, "Locally-deleted resource has been changed on the server in the meanwhile"); Log.i(TAG, "Locally-deleted resource has been changed on the server in the meanwhile");
} }
// always delete locally so that the record with the DELETED flag doesn't cause another deletion attempt
local.delete(res); local.delete(res);
count++; count++;
@ -149,7 +149,7 @@ public class SyncManager {
local.updateETag(res, eTag); local.updateETag(res, eTag);
local.clearDirty(res); local.clearDirty(res);
count++; count++;
} catch (PreconditionFailedException|ConflictException e) { } catch (ConflictException|PreconditionFailedException e) {
Log.i(TAG, "Didn't overwrite existing resource with other content"); Log.i(TAG, "Didn't overwrite existing resource with other content");
} catch (RecordNotFoundException e) { } catch (RecordNotFoundException e) {
Log.wtf(TAG, "Couldn't read new record", e); Log.wtf(TAG, "Couldn't read new record", e);
@ -173,8 +173,10 @@ public class SyncManager {
local.updateETag(res, eTag); local.updateETag(res, eTag);
local.clearDirty(res); local.clearDirty(res);
count++; count++;
} catch (PreconditionFailedException|ConflictException e) { } catch (ForbiddenException e) {
Log.i(TAG, "Locally changed resource has been changed on the server in the meanwhile"); Log.w(TAG, "Server has rejected local changes, server wins", e);
} catch (ConflictException|PreconditionFailedException e) {
Log.i(TAG, "Locally changed resource has been changed on the server in the meanwhile", e);
} catch (RecordNotFoundException e) { } catch (RecordNotFoundException e) {
Log.e(TAG, "Couldn't read dirty record", e); Log.e(TAG, "Couldn't read dirty record", e);
} }

View File

@ -0,0 +1,19 @@
/*
* Copyright © 2013 2015 Ricki Hirner (bitfire web engineering).
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the GNU Public License v3.0
* which accompanies this distribution, and is available at
* http://www.gnu.org/licenses/gpl.html
*/
package at.bitfire.davdroid.webdav;
import org.apache.http.HttpStatus;
public class ForbiddenException extends HttpException {
private static final long serialVersionUID = 102282229174086113L;
public ForbiddenException(String reason) {
super(HttpStatus.SC_FORBIDDEN, reason);
}
}

View File

@ -345,6 +345,8 @@ public class WebDavResource {
switch (code) { switch (code) {
case HttpStatus.SC_UNAUTHORIZED: case HttpStatus.SC_UNAUTHORIZED:
throw new NotAuthorizedException(reason); throw new NotAuthorizedException(reason);
case HttpStatus.SC_FORBIDDEN:
throw new ForbiddenException(reason);
case HttpStatus.SC_NOT_FOUND: case HttpStatus.SC_NOT_FOUND:
throw new NotFoundException(reason); throw new NotFoundException(reason);
case HttpStatus.SC_CONFLICT: case HttpStatus.SC_CONFLICT:

View File

@ -76,7 +76,7 @@
<a href="http://davdroid.bitfire.at/donate?pk_campaign=davdroid-app&amp;pk_kwd=main-activity">für DAVdroid spenden</a> oder die App kaufen.</p> <a href="http://davdroid.bitfire.at/donate?pk_campaign=davdroid-app&amp;pk_kwd=main-activity">für DAVdroid spenden</a> oder die App kaufen.</p>
<h1>Lizenz</h1> <h1>Lizenz</h1>
<p>Copyright © 2013 2014 Ricki Hirner, Bernhard Stockmann (<a href="http://www.bitfire.at">bitfire web engineering</a>), alle Rechte <p>Copyright © 2013 2015 Ricki Hirner, Bernhard Stockmann (<a href="http://www.bitfire.at">bitfire web engineering</a>), alle Rechte
vorbehalten. Dieses Programm ist freie Software. Sie können es unter den Bedingungen der <a href="http://www.gnu.org/licenses/gpl.html">GNU vorbehalten. Dieses Programm ist freie Software. Sie können es unter den Bedingungen der <a href="http://www.gnu.org/licenses/gpl.html">GNU
General Public License Version 3</a>, wie von der Free Software Foundation veröffentlicht, weitergeben und/oder modifizieren. General Public License Version 3</a>, wie von der Free Software Foundation veröffentlicht, weitergeben und/oder modifizieren.
Sofern Google Play oder Samsung Store andere Bedingungen benötigen, gelten für über den jeweiligen Markt heruntergeladene Sofern Google Play oder Samsung Store andere Bedingungen benötigen, gelten für über den jeweiligen Markt heruntergeladene