/* * * * Copyright (C) 2014 Open Whisper Systems * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * / */ package org.anhonesteffort.flock.sync.calendar; import android.content.Context; import android.content.OperationApplicationException; import android.content.SyncResult; import android.os.RemoteException; import org.anhonesteffort.flock.util.guava.Optional; import org.anhonesteffort.flock.sync.SyncWorkerUtil; import org.anhonesteffort.flock.webdav.caldav.CalDavConstants; import net.fortuna.ical4j.model.Calendar; import net.fortuna.ical4j.model.ConstraintViolationException; import net.fortuna.ical4j.model.Property; import net.fortuna.ical4j.model.component.VEvent; import net.fortuna.ical4j.model.property.Uid; import net.fortuna.ical4j.util.Calendars; import org.anhonesteffort.flock.crypto.InvalidMacException; import org.anhonesteffort.flock.sync.AbstractDavSyncWorker; import org.anhonesteffort.flock.webdav.PropertyParseException; import org.apache.jackrabbit.webdav.DavException; import org.apache.jackrabbit.webdav.xml.Namespace; import java.io.IOException; import java.security.GeneralSecurityException; /** * Programmer: rhodey */ public class CalendarSyncWorker extends AbstractDavSyncWorker<Calendar> { private static final String TAG = "org.anhonesteffort.flock.sync.calendar.CalendarSyncWorker"; protected CalendarSyncWorker(Context context, SyncResult result, LocalEventCollection localCollection, HidingCalDavCollection remoteCollection) { super(context, result, localCollection, remoteCollection); Thread.currentThread().setContextClassLoader(context.getClassLoader()); } private LocalEventCollection getLocalCollection() { return (LocalEventCollection) localCollection; } private HidingCalDavCollection getRemoteHidingCollection() { return (HidingCalDavCollection) remoteCollection; } @Override protected Namespace getNamespace() { return CalDavConstants.CALDAV_NAMESPACE; } @Override protected Optional<String> getComponentUid(Calendar component) { try { Uid uid = Calendars.getUid(component); if (uid != null) return Optional.of(uid.getValue()); return Optional.absent(); } catch (ConstraintViolationException e) { return Optional.absent(); } } @Override protected void prePushLocallyCreatedComponent(Calendar component) { VEvent vEvent = (VEvent) component.getComponent(VEvent.VEVENT); if (vEvent != null) { Property copyIdProp = vEvent.getProperty(EventFactory.PROPERTY_NAME_FLOCK_COPY_EVENT_ID); if (copyIdProp != null) vEvent.getProperties().remove(copyIdProp); } } @Override protected void pushLocallyCreatedProperties(SyncResult result) { super.pushLocallyCreatedProperties(result); handleLogMessage("pushLocallyCreatedProperties()"); try { Optional<Integer> localColor = getLocalCollection().getColor(); if (localColor.isPresent()) { Optional<Integer> remoteColor = getRemoteHidingCollection().getHiddenColor(); if (!remoteColor.isPresent()) { handleLogMessage("remote hidden color not present, setting using local"); getRemoteHidingCollection().setHiddenColor(localColor.get()); result.stats.numInserts++; } } } catch (IOException e) { SyncWorkerUtil.handleException(context, e, result); } catch (RemoteException e) { SyncWorkerUtil.handleException(context, e, result); } catch (PropertyParseException e) { SyncWorkerUtil.handleException(context, e, result); } catch (DavException e) { SyncWorkerUtil.handleException(context, e, result); } catch (InvalidMacException e) { SyncWorkerUtil.handleException(context, e, result); } catch (GeneralSecurityException e){ SyncWorkerUtil.handleException(context, e, result); } try { Optional<Calendar> localTimeZone = getLocalCollection().getTimeZone(); if (localTimeZone.isPresent()) { Optional<Calendar> remoteTimeZone = getRemoteHidingCollection().getTimeZone(); if (!remoteTimeZone.isPresent()) { handleLogMessage("remote time zone not present, setting using local"); getRemoteHidingCollection().setTimeZone(localTimeZone.get()); result.stats.numInserts++; } } } catch (IOException e) { SyncWorkerUtil.handleException(context, e, result); } catch (RemoteException e) { SyncWorkerUtil.handleException(context, e, result); } catch (PropertyParseException e) { SyncWorkerUtil.handleException(context, e, result); } catch (DavException e) { SyncWorkerUtil.handleException(context, e, result); } } @Override protected void pushLocallyChangedProperties(SyncResult result) { super.pushLocallyChangedProperties(result); handleLogMessage("pushLocallyChangedProperties()"); if (localCTag.isPresent() && remoteCTag.isPresent() && localCTag.get().equals(remoteCTag.get())) { try { Optional<Integer> localColor = getLocalCollection().getColor(); if (localColor.isPresent()) { Optional<Integer> remoteColor = getRemoteHidingCollection().getHiddenColor(); if (remoteColor.isPresent() && !localColor.get().equals(remoteColor.get())) { handleLogMessage("remote hidden color present, updating using local"); getRemoteHidingCollection().setHiddenColor(localColor.get()); result.stats.numUpdates++; } } } catch (IOException e) { SyncWorkerUtil.handleException(context, e, result); } catch (RemoteException e) { SyncWorkerUtil.handleException(context, e, result); } catch (PropertyParseException e) { SyncWorkerUtil.handleException(context, e, result); } catch (DavException e) { SyncWorkerUtil.handleException(context, e, result); } catch (InvalidMacException e) { SyncWorkerUtil.handleException(context, e, result); } catch (GeneralSecurityException e){ SyncWorkerUtil.handleException(context, e, result); } try { Optional<Calendar> localTimeZone = getLocalCollection().getTimeZone(); if (localTimeZone.isPresent()) { Optional<Calendar> remoteTimeZone = getRemoteHidingCollection().getTimeZone(); if (remoteTimeZone.isPresent() && !localTimeZone.get().equals(remoteTimeZone.get())) { handleLogMessage("remote time zone present, updating using local"); getRemoteHidingCollection().setTimeZone(localTimeZone.get()); result.stats.numUpdates++; } } } catch (IOException e) { SyncWorkerUtil.handleException(context, e, result); } catch (RemoteException e) { SyncWorkerUtil.handleException(context, e, result); } catch (PropertyParseException e) { SyncWorkerUtil.handleException(context, e, result); } catch (DavException e) { SyncWorkerUtil.handleException(context, e, result); } } } @Override protected void pullRemotelyCreatedProperties(SyncResult result) { super.pullRemotelyCreatedProperties(result); handleLogMessage("pullRemotelyCreatedProperties()"); try { Optional<Integer> remoteColor = getRemoteHidingCollection().getHiddenColor(); if (remoteColor.isPresent()) { Optional<Integer> localColor = getLocalCollection().getColor(); if (!localColor.isPresent()) { handleLogMessage("local color not present, setting using remote"); getLocalCollection().setColor(remoteColor.get()); localCollection.commitPendingOperations(); result.stats.numInserts++; } } } catch (RemoteException e) { SyncWorkerUtil.handleException(context, e, result); } catch (OperationApplicationException e) { SyncWorkerUtil.handleException(context, e, result); } catch (PropertyParseException e) { SyncWorkerUtil.handleException(context, e, result); } catch (InvalidMacException e) { SyncWorkerUtil.handleException(context, e, result); } catch (GeneralSecurityException e){ SyncWorkerUtil.handleException(context, e, result); } catch (IOException e) { SyncWorkerUtil.handleException(context, e, result); } try { Optional<Calendar> remoteTimeZone = getRemoteHidingCollection().getTimeZone(); if (remoteTimeZone.isPresent()) { Optional<Calendar> localTimeZone = getLocalCollection().getTimeZone(); if (!localTimeZone.isPresent()) { handleLogMessage("local time zone not present, setting using remote"); getLocalCollection().setTimeZone(remoteTimeZone.get()); localCollection.commitPendingOperations(); result.stats.numInserts++; } } } catch (RemoteException e) { SyncWorkerUtil.handleException(context, e, result); } catch (OperationApplicationException e) { SyncWorkerUtil.handleException(context, e, result); } catch (PropertyParseException e) { SyncWorkerUtil.handleException(context, e, result); } } @Override protected void pullRemotelyChangedProperties(SyncResult result) { super.pullRemotelyChangedProperties(result); handleLogMessage("pullRemotelyChangedProperties()"); if (localCTag.isPresent() && remoteCTag.isPresent() && !localCTag.get().equals(remoteCTag.get())) { try { Optional<Integer> remoteColor = getRemoteHidingCollection().getHiddenColor(); if (remoteColor.isPresent()) { Optional<Integer> localColor = getLocalCollection().getColor(); if (localColor.isPresent() && !localColor.get().equals(remoteColor.get())) { handleLogMessage("local color present, updating using remote"); getLocalCollection().setColor(remoteColor.get()); localCollection.commitPendingOperations(); result.stats.numUpdates++; } } } catch (RemoteException e) { SyncWorkerUtil.handleException(context, e, result); } catch (OperationApplicationException e) { SyncWorkerUtil.handleException(context, e, result); } catch (PropertyParseException e) { SyncWorkerUtil.handleException(context, e, result); } catch (InvalidMacException e) { SyncWorkerUtil.handleException(context, e, result); } catch (GeneralSecurityException e){ SyncWorkerUtil.handleException(context, e, result); } catch (IOException e) { SyncWorkerUtil.handleException(context, e, result); } try { Optional<Calendar> remoteTimeZone = getRemoteHidingCollection().getTimeZone(); if (remoteTimeZone.isPresent()) { Optional<Calendar> localTimeZone = getLocalCollection().getTimeZone(); if (localTimeZone.isPresent() && !localTimeZone.get().equals(remoteTimeZone.get())) { handleLogMessage("local time zone present, updating using remote"); getLocalCollection().setTimeZone(remoteTimeZone.get()); localCollection.commitPendingOperations(); result.stats.numUpdates++; } } } catch (RemoteException e) { SyncWorkerUtil.handleException(context, e, result); } catch (OperationApplicationException e) { SyncWorkerUtil.handleException(context, e, result); } catch (PropertyParseException e) { SyncWorkerUtil.handleException(context, e, result); } } } }