Loading app/src/main/java/at/bitfire/davdroid/Constants.java +0 −2 Original line number Diff line number Diff line Loading @@ -17,7 +17,5 @@ public class Constants { WEB_URL_HELP = "https://davdroid.bitfire.at/configuration?pk_campaign=davdroid-app", WEB_URL_VIEW_LOGS = "https://github.com/bitfireAT/davdroid/wiki/How-to-view-the-logs"; //public static final ProdId ICAL_PRODID = new ProdId("-//bitfire web engineering//DAVdroid " + BuildConfig.VERSION_CODE + " (ical4j 2.0-beta1)//EN"); public static final Logger log = LoggerFactory.getLogger("davdroid"); } app/src/main/java/at/bitfire/davdroid/HttpClient.java +0 −3 Original line number Diff line number Diff line Loading @@ -118,9 +118,6 @@ public class HttpClient extends OkHttpClient { } } // don't follow redirects automatically because this may rewrite DAV methods to GET setFollowRedirects(false); // set timeouts setConnectTimeout(30, TimeUnit.SECONDS); setWriteTimeout(15, TimeUnit.SECONDS); Loading app/src/main/java/at/bitfire/davdroid/resource/LocalCalendar.java +114 −9 Original line number Diff line number Diff line Loading @@ -10,10 +10,13 @@ package at.bitfire.davdroid.resource; import android.accounts.Account; import android.content.ContentProviderClient; import android.content.ContentProviderOperation; import android.content.ContentResolver; import android.content.ContentUris; import android.content.ContentValues; import android.database.Cursor; import android.net.Uri; import android.os.Build; import android.os.RemoteException; import android.provider.CalendarContract; import android.provider.CalendarContract.Calendars; Loading @@ -22,8 +25,14 @@ import android.provider.CalendarContract.Reminders; import com.google.common.base.Joiner; import java.io.FileNotFoundException; import java.util.LinkedList; import java.util.List; import at.bitfire.davdroid.Constants; import at.bitfire.ical4android.AndroidCalendar; import at.bitfire.ical4android.AndroidCalendarFactory; import at.bitfire.ical4android.BatchOperation; import at.bitfire.ical4android.CalendarStorageException; import at.bitfire.vcard4android.ContactsStorageException; import lombok.Cleanup; Loading @@ -34,9 +43,13 @@ public class LocalCalendar extends AndroidCalendar implements LocalCollection { public static final String COLUMN_CTAG = Calendars.CAL_SYNC1; protected static final int DIRTY_INCREASE_SEQUENCE = 1, DIRTY_DONT_INCREASE_SEQUENCE = 2; static String[] BASE_INFO_COLUMNS = new String[] { Events._ID, LocalEvent.COLUMN_FILENAME, Events._SYNC_ID, LocalEvent.COLUMN_ETAG }; Loading @@ -59,38 +72,61 @@ public class LocalCalendar extends AndroidCalendar implements LocalCollection { values.put(Calendars.NAME, info.getURL()); values.put(Calendars.CALENDAR_DISPLAY_NAME, info.getTitle()); values.put(Calendars.CALENDAR_COLOR, info.color != null ? info.color : defaultColor); values.put(Calendars.CALENDAR_ACCESS_LEVEL, info.readOnly ? Calendars.CAL_ACCESS_READ : Calendars.CAL_ACCESS_OWNER); if (info.isReadOnly()) values.put(Calendars.CALENDAR_ACCESS_LEVEL, Calendars.CAL_ACCESS_READ); else { values.put(Calendars.CALENDAR_ACCESS_LEVEL, Calendars.CAL_ACCESS_OWNER); values.put(Calendars.CAN_MODIFY_TIME_ZONE, 1); values.put(Calendars.CAN_ORGANIZER_RESPOND, 1); } values.put(Calendars.OWNER_ACCOUNT, account.name); values.put(Calendars.SYNC_EVENTS, 1); values.put(Calendars.VISIBLE, 1); if (info.timezone != null) { // TODO parse VTIMEZONE // values.put(Calendars.CALENDAR_TIME_ZONE, DateUtils.findAndroidTimezoneID(info.timezone)); } values.put(Calendars.ALLOWED_REMINDERS, Reminders.METHOD_ALERT); if (Build.VERSION.SDK_INT >= 15) { values.put(Calendars.ALLOWED_AVAILABILITY, Joiner.on(",").join(Reminders.AVAILABILITY_TENTATIVE, Reminders.AVAILABILITY_FREE, Reminders.AVAILABILITY_BUSY)); values.put(Calendars.ALLOWED_ATTENDEE_TYPES, Joiner.on(",").join(CalendarContract.Attendees.TYPE_OPTIONAL, CalendarContract.Attendees.TYPE_REQUIRED, CalendarContract.Attendees.TYPE_RESOURCE)); } return create(account, provider, values); } @Override public LocalResource[] getAll() throws CalendarStorageException, ContactsStorageException { return (LocalEvent[])queryEvents(null, null); return (LocalEvent[])queryEvents(Events.ORIGINAL_ID + " IS NULL", null); } @Override public LocalEvent[] getDeleted() throws CalendarStorageException { return (LocalEvent[])queryEvents(Events.DELETED + "!=0", null); return (LocalEvent[])queryEvents(Events.DELETED + "!=0 AND " + Events.ORIGINAL_ID + " IS NULL", null); } @Override public LocalEvent[] getWithoutFileName() throws CalendarStorageException { return (LocalEvent[])queryEvents(LocalEvent.COLUMN_FILENAME + " IS NULL", null); return (LocalEvent[])queryEvents(Events._SYNC_ID + " IS NULL AND " + Events.ORIGINAL_ID + " IS NULL", null); } @Override public LocalResource[] getDirty() throws CalendarStorageException { return (LocalEvent[])queryEvents(Events.DIRTY + "!=0", null); public LocalResource[] getDirty() throws CalendarStorageException, FileNotFoundException { List<LocalResource> dirty = new LinkedList<>(); // get dirty events which are not required to have an increased SEQUENCE value for (LocalEvent event : (LocalEvent[])queryEvents(Events.DIRTY + "=" + DIRTY_DONT_INCREASE_SEQUENCE + " AND " + Events.ORIGINAL_ID + " IS NULL", null)) dirty.add(event); // get dirty events which are required to have an increased SEQUENCE value for (LocalEvent event : (LocalEvent[])queryEvents(Events.DIRTY + "=" + DIRTY_INCREASE_SEQUENCE + " AND " + Events.ORIGINAL_ID + " IS NULL", null)) { event.getEvent().sequence++; dirty.add(event); } return dirty.toArray(new LocalResource[dirty.size()]); } Loading @@ -117,6 +153,75 @@ public class LocalCalendar extends AndroidCalendar implements LocalCollection { } } public void processDirtyExceptions() throws CalendarStorageException { // process deleted exceptions Constants.log.info("Processing deleted exceptions"); try { @Cleanup Cursor cursor = provider.query( syncAdapterURI(Events.CONTENT_URI), new String[] { Events._ID, Events.ORIGINAL_ID, LocalEvent.COLUMN_SEQUENCE }, Events.DELETED + "!=0 AND " + Events.ORIGINAL_ID + " IS NOT NULL", null, null); while (cursor != null && cursor.moveToNext()) { Constants.log.debug("Found deleted exception, removing; then re-schuling original event"); long id = cursor.getLong(0), // can't be null (by definition) originalID = cursor.getLong(1); // can't be null (by query) int sequence = cursor.isNull(2) ? 0 : cursor.getInt(2); // get original event's SEQUENCE @Cleanup Cursor cursor2 = provider.query( syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, originalID)), new String[] { LocalEvent.COLUMN_SEQUENCE }, null, null, null); int originalSequence = cursor.isNull(0) ? 0 : cursor.getInt(0); BatchOperation batch = new BatchOperation(provider); // re-schedule original event and set it to DIRTY batch.enqueue(ContentProviderOperation.newUpdate( syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, originalID))) .withValue(LocalEvent.COLUMN_SEQUENCE, originalSequence) .withValue(Events.DIRTY, DIRTY_INCREASE_SEQUENCE) .build()); // remove exception batch.enqueue(ContentProviderOperation.newDelete( syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, id))).build()); batch.commit(); } } catch (RemoteException e) { throw new CalendarStorageException("Couldn't process locally modified exception", e); } // process dirty exceptions Constants.log.info("Processing dirty exceptions"); try { @Cleanup Cursor cursor = provider.query( syncAdapterURI(Events.CONTENT_URI), new String[] { Events._ID, Events.ORIGINAL_ID, LocalEvent.COLUMN_SEQUENCE }, Events.DIRTY + "!=0 AND " + Events.ORIGINAL_ID + " IS NOT NULL", null, null); while (cursor != null && cursor.moveToNext()) { Constants.log.debug("Found dirty exception, increasing SEQUENCE to re-schedule"); long id = cursor.getLong(0), // can't be null (by definition) originalID = cursor.getLong(1); // can't be null (by query) int sequence = cursor.isNull(2) ? 0 : cursor.getInt(2); BatchOperation batch = new BatchOperation(provider); // original event to DIRTY batch.enqueue(ContentProviderOperation.newUpdate( syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, originalID))) .withValue(Events.DIRTY, DIRTY_DONT_INCREASE_SEQUENCE) .build()); // increase SEQUENCE and set DIRTY to 0 batch.enqueue(ContentProviderOperation.newUpdate( syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, id))) .withValue(LocalEvent.COLUMN_SEQUENCE, sequence + 1) .withValue(Events.DIRTY, 0) .build()); batch.commit(); } } catch (RemoteException e) { throw new CalendarStorageException("Couldn't process locally modified exception", e); } } public static class Factory implements AndroidCalendarFactory { public static final Factory INSTANCE = new Factory(); Loading app/src/main/java/at/bitfire/davdroid/resource/LocalCollection.java +3 −1 Original line number Diff line number Diff line Loading @@ -10,6 +10,8 @@ package at.bitfire.davdroid.resource; import android.provider.ContactsContract; import java.io.FileNotFoundException; import at.bitfire.ical4android.CalendarStorageException; import at.bitfire.vcard4android.ContactsStorageException; Loading @@ -17,7 +19,7 @@ public interface LocalCollection { LocalResource[] getDeleted() throws CalendarStorageException, ContactsStorageException; LocalResource[] getWithoutFileName() throws CalendarStorageException, ContactsStorageException; LocalResource[] getDirty() throws CalendarStorageException, ContactsStorageException; LocalResource[] getDirty() throws CalendarStorageException, ContactsStorageException, FileNotFoundException; LocalResource[] getAll() throws CalendarStorageException, ContactsStorageException; Loading app/src/main/java/at/bitfire/davdroid/resource/LocalContact.java +1 −1 Original line number Diff line number Diff line Loading @@ -22,7 +22,7 @@ import ezvcard.Ezvcard; public class LocalContact extends AndroidContact implements LocalResource { static { Contact.productID = "+//IDN bitfire.at//DAVdroid/" + BuildConfig.VERSION_NAME + " ez-vcard/" + Ezvcard.VERSION; Contact.productID = "+//IDN bitfire.at//DAVdroid/" + BuildConfig.VERSION_NAME + "vcard4android ez-vcard/" + Ezvcard.VERSION; } protected LocalContact(AndroidAddressBook addressBook, long id, String fileName, String eTag) { Loading Loading
app/src/main/java/at/bitfire/davdroid/Constants.java +0 −2 Original line number Diff line number Diff line Loading @@ -17,7 +17,5 @@ public class Constants { WEB_URL_HELP = "https://davdroid.bitfire.at/configuration?pk_campaign=davdroid-app", WEB_URL_VIEW_LOGS = "https://github.com/bitfireAT/davdroid/wiki/How-to-view-the-logs"; //public static final ProdId ICAL_PRODID = new ProdId("-//bitfire web engineering//DAVdroid " + BuildConfig.VERSION_CODE + " (ical4j 2.0-beta1)//EN"); public static final Logger log = LoggerFactory.getLogger("davdroid"); }
app/src/main/java/at/bitfire/davdroid/HttpClient.java +0 −3 Original line number Diff line number Diff line Loading @@ -118,9 +118,6 @@ public class HttpClient extends OkHttpClient { } } // don't follow redirects automatically because this may rewrite DAV methods to GET setFollowRedirects(false); // set timeouts setConnectTimeout(30, TimeUnit.SECONDS); setWriteTimeout(15, TimeUnit.SECONDS); Loading
app/src/main/java/at/bitfire/davdroid/resource/LocalCalendar.java +114 −9 Original line number Diff line number Diff line Loading @@ -10,10 +10,13 @@ package at.bitfire.davdroid.resource; import android.accounts.Account; import android.content.ContentProviderClient; import android.content.ContentProviderOperation; import android.content.ContentResolver; import android.content.ContentUris; import android.content.ContentValues; import android.database.Cursor; import android.net.Uri; import android.os.Build; import android.os.RemoteException; import android.provider.CalendarContract; import android.provider.CalendarContract.Calendars; Loading @@ -22,8 +25,14 @@ import android.provider.CalendarContract.Reminders; import com.google.common.base.Joiner; import java.io.FileNotFoundException; import java.util.LinkedList; import java.util.List; import at.bitfire.davdroid.Constants; import at.bitfire.ical4android.AndroidCalendar; import at.bitfire.ical4android.AndroidCalendarFactory; import at.bitfire.ical4android.BatchOperation; import at.bitfire.ical4android.CalendarStorageException; import at.bitfire.vcard4android.ContactsStorageException; import lombok.Cleanup; Loading @@ -34,9 +43,13 @@ public class LocalCalendar extends AndroidCalendar implements LocalCollection { public static final String COLUMN_CTAG = Calendars.CAL_SYNC1; protected static final int DIRTY_INCREASE_SEQUENCE = 1, DIRTY_DONT_INCREASE_SEQUENCE = 2; static String[] BASE_INFO_COLUMNS = new String[] { Events._ID, LocalEvent.COLUMN_FILENAME, Events._SYNC_ID, LocalEvent.COLUMN_ETAG }; Loading @@ -59,38 +72,61 @@ public class LocalCalendar extends AndroidCalendar implements LocalCollection { values.put(Calendars.NAME, info.getURL()); values.put(Calendars.CALENDAR_DISPLAY_NAME, info.getTitle()); values.put(Calendars.CALENDAR_COLOR, info.color != null ? info.color : defaultColor); values.put(Calendars.CALENDAR_ACCESS_LEVEL, info.readOnly ? Calendars.CAL_ACCESS_READ : Calendars.CAL_ACCESS_OWNER); if (info.isReadOnly()) values.put(Calendars.CALENDAR_ACCESS_LEVEL, Calendars.CAL_ACCESS_READ); else { values.put(Calendars.CALENDAR_ACCESS_LEVEL, Calendars.CAL_ACCESS_OWNER); values.put(Calendars.CAN_MODIFY_TIME_ZONE, 1); values.put(Calendars.CAN_ORGANIZER_RESPOND, 1); } values.put(Calendars.OWNER_ACCOUNT, account.name); values.put(Calendars.SYNC_EVENTS, 1); values.put(Calendars.VISIBLE, 1); if (info.timezone != null) { // TODO parse VTIMEZONE // values.put(Calendars.CALENDAR_TIME_ZONE, DateUtils.findAndroidTimezoneID(info.timezone)); } values.put(Calendars.ALLOWED_REMINDERS, Reminders.METHOD_ALERT); if (Build.VERSION.SDK_INT >= 15) { values.put(Calendars.ALLOWED_AVAILABILITY, Joiner.on(",").join(Reminders.AVAILABILITY_TENTATIVE, Reminders.AVAILABILITY_FREE, Reminders.AVAILABILITY_BUSY)); values.put(Calendars.ALLOWED_ATTENDEE_TYPES, Joiner.on(",").join(CalendarContract.Attendees.TYPE_OPTIONAL, CalendarContract.Attendees.TYPE_REQUIRED, CalendarContract.Attendees.TYPE_RESOURCE)); } return create(account, provider, values); } @Override public LocalResource[] getAll() throws CalendarStorageException, ContactsStorageException { return (LocalEvent[])queryEvents(null, null); return (LocalEvent[])queryEvents(Events.ORIGINAL_ID + " IS NULL", null); } @Override public LocalEvent[] getDeleted() throws CalendarStorageException { return (LocalEvent[])queryEvents(Events.DELETED + "!=0", null); return (LocalEvent[])queryEvents(Events.DELETED + "!=0 AND " + Events.ORIGINAL_ID + " IS NULL", null); } @Override public LocalEvent[] getWithoutFileName() throws CalendarStorageException { return (LocalEvent[])queryEvents(LocalEvent.COLUMN_FILENAME + " IS NULL", null); return (LocalEvent[])queryEvents(Events._SYNC_ID + " IS NULL AND " + Events.ORIGINAL_ID + " IS NULL", null); } @Override public LocalResource[] getDirty() throws CalendarStorageException { return (LocalEvent[])queryEvents(Events.DIRTY + "!=0", null); public LocalResource[] getDirty() throws CalendarStorageException, FileNotFoundException { List<LocalResource> dirty = new LinkedList<>(); // get dirty events which are not required to have an increased SEQUENCE value for (LocalEvent event : (LocalEvent[])queryEvents(Events.DIRTY + "=" + DIRTY_DONT_INCREASE_SEQUENCE + " AND " + Events.ORIGINAL_ID + " IS NULL", null)) dirty.add(event); // get dirty events which are required to have an increased SEQUENCE value for (LocalEvent event : (LocalEvent[])queryEvents(Events.DIRTY + "=" + DIRTY_INCREASE_SEQUENCE + " AND " + Events.ORIGINAL_ID + " IS NULL", null)) { event.getEvent().sequence++; dirty.add(event); } return dirty.toArray(new LocalResource[dirty.size()]); } Loading @@ -117,6 +153,75 @@ public class LocalCalendar extends AndroidCalendar implements LocalCollection { } } public void processDirtyExceptions() throws CalendarStorageException { // process deleted exceptions Constants.log.info("Processing deleted exceptions"); try { @Cleanup Cursor cursor = provider.query( syncAdapterURI(Events.CONTENT_URI), new String[] { Events._ID, Events.ORIGINAL_ID, LocalEvent.COLUMN_SEQUENCE }, Events.DELETED + "!=0 AND " + Events.ORIGINAL_ID + " IS NOT NULL", null, null); while (cursor != null && cursor.moveToNext()) { Constants.log.debug("Found deleted exception, removing; then re-schuling original event"); long id = cursor.getLong(0), // can't be null (by definition) originalID = cursor.getLong(1); // can't be null (by query) int sequence = cursor.isNull(2) ? 0 : cursor.getInt(2); // get original event's SEQUENCE @Cleanup Cursor cursor2 = provider.query( syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, originalID)), new String[] { LocalEvent.COLUMN_SEQUENCE }, null, null, null); int originalSequence = cursor.isNull(0) ? 0 : cursor.getInt(0); BatchOperation batch = new BatchOperation(provider); // re-schedule original event and set it to DIRTY batch.enqueue(ContentProviderOperation.newUpdate( syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, originalID))) .withValue(LocalEvent.COLUMN_SEQUENCE, originalSequence) .withValue(Events.DIRTY, DIRTY_INCREASE_SEQUENCE) .build()); // remove exception batch.enqueue(ContentProviderOperation.newDelete( syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, id))).build()); batch.commit(); } } catch (RemoteException e) { throw new CalendarStorageException("Couldn't process locally modified exception", e); } // process dirty exceptions Constants.log.info("Processing dirty exceptions"); try { @Cleanup Cursor cursor = provider.query( syncAdapterURI(Events.CONTENT_URI), new String[] { Events._ID, Events.ORIGINAL_ID, LocalEvent.COLUMN_SEQUENCE }, Events.DIRTY + "!=0 AND " + Events.ORIGINAL_ID + " IS NOT NULL", null, null); while (cursor != null && cursor.moveToNext()) { Constants.log.debug("Found dirty exception, increasing SEQUENCE to re-schedule"); long id = cursor.getLong(0), // can't be null (by definition) originalID = cursor.getLong(1); // can't be null (by query) int sequence = cursor.isNull(2) ? 0 : cursor.getInt(2); BatchOperation batch = new BatchOperation(provider); // original event to DIRTY batch.enqueue(ContentProviderOperation.newUpdate( syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, originalID))) .withValue(Events.DIRTY, DIRTY_DONT_INCREASE_SEQUENCE) .build()); // increase SEQUENCE and set DIRTY to 0 batch.enqueue(ContentProviderOperation.newUpdate( syncAdapterURI(ContentUris.withAppendedId(Events.CONTENT_URI, id))) .withValue(LocalEvent.COLUMN_SEQUENCE, sequence + 1) .withValue(Events.DIRTY, 0) .build()); batch.commit(); } } catch (RemoteException e) { throw new CalendarStorageException("Couldn't process locally modified exception", e); } } public static class Factory implements AndroidCalendarFactory { public static final Factory INSTANCE = new Factory(); Loading
app/src/main/java/at/bitfire/davdroid/resource/LocalCollection.java +3 −1 Original line number Diff line number Diff line Loading @@ -10,6 +10,8 @@ package at.bitfire.davdroid.resource; import android.provider.ContactsContract; import java.io.FileNotFoundException; import at.bitfire.ical4android.CalendarStorageException; import at.bitfire.vcard4android.ContactsStorageException; Loading @@ -17,7 +19,7 @@ public interface LocalCollection { LocalResource[] getDeleted() throws CalendarStorageException, ContactsStorageException; LocalResource[] getWithoutFileName() throws CalendarStorageException, ContactsStorageException; LocalResource[] getDirty() throws CalendarStorageException, ContactsStorageException; LocalResource[] getDirty() throws CalendarStorageException, ContactsStorageException, FileNotFoundException; LocalResource[] getAll() throws CalendarStorageException, ContactsStorageException; Loading
app/src/main/java/at/bitfire/davdroid/resource/LocalContact.java +1 −1 Original line number Diff line number Diff line Loading @@ -22,7 +22,7 @@ import ezvcard.Ezvcard; public class LocalContact extends AndroidContact implements LocalResource { static { Contact.productID = "+//IDN bitfire.at//DAVdroid/" + BuildConfig.VERSION_NAME + " ez-vcard/" + Ezvcard.VERSION; Contact.productID = "+//IDN bitfire.at//DAVdroid/" + BuildConfig.VERSION_NAME + "vcard4android ez-vcard/" + Ezvcard.VERSION; } protected LocalContact(AndroidAddressBook addressBook, long id, String fileName, String eTag) { Loading