Implement remote filters to fetch only CalDAV resources with useful components (VEVENT for now)

This commit is contained in:
Ricki Hirner 2015-05-15 23:35:27 +02:00
parent 1326e8bbdc
commit c1671b7d62
9 changed files with 147 additions and 10 deletions

View file

@ -8,15 +8,30 @@
package at.bitfire.davdroid.resource;
import android.accounts.Account;
import android.util.Log;
import org.apache.http.impl.client.CloseableHttpClient;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;
import java.io.StringWriter;
import java.net.URISyntaxException;
import at.bitfire.davdroid.syncadapter.AccountSettings;
import at.bitfire.davdroid.webdav.DavCalendarQuery;
import at.bitfire.davdroid.webdav.DavCompFilter;
import at.bitfire.davdroid.webdav.DavFilter;
import at.bitfire.davdroid.webdav.DavMultiget;
import at.bitfire.davdroid.webdav.DavProp;
public class CalDavCalendar extends RemoteCollection<Event> {
private final static String TAG = "davdroid.CalDAVCalendar";
public CalDavCalendar(CloseableHttpClient httpClient, String baseURL, String user, String password, boolean preemptiveAuth) throws URISyntaxException {
super(httpClient, baseURL, user, password, preemptiveAuth);
}
public class CalDavCalendar extends RemoteCollection<Event> {
@Override
protected String memberAcceptedMimeTypes()
@ -35,7 +50,33 @@ public class CalDavCalendar extends RemoteCollection<Event> {
}
public CalDavCalendar(CloseableHttpClient httpClient, String baseURL, String user, String password, boolean preemptiveAuth) throws URISyntaxException {
super(httpClient, baseURL, user, password, preemptiveAuth);
@Override
public String getMemberETagsQuery() {
DavCalendarQuery query = new DavCalendarQuery();
// prop
DavProp prop = new DavProp();
prop.setGetetag(new DavProp.GetETag());
query.setProp(prop);
// filter
DavFilter filter = new DavFilter();
query.setFilter(filter);
DavCompFilter compFilter = new DavCompFilter("VCALENDAR");
filter.setCompFilter(compFilter);
compFilter.setCompFilter(new DavCompFilter("VEVENT"));
Serializer serializer = new Persister();
StringWriter writer = new StringWriter();
try {
serializer.write(query, writer);
} catch (Exception e) {
Log.e(TAG, "Couldn't prepare REPORT query", e);
return null;
}
return writer.toString();
}
}

View file

@ -26,7 +26,9 @@ import java.util.List;
import at.bitfire.davdroid.URIUtils;
import at.bitfire.davdroid.syncadapter.AccountSettings;
import at.bitfire.davdroid.webdav.DavCalendarQuery;
import at.bitfire.davdroid.webdav.DavException;
import at.bitfire.davdroid.webdav.DavFilter;
import at.bitfire.davdroid.webdav.DavMultiget;
import at.bitfire.davdroid.webdav.DavNoContentException;
import at.bitfire.davdroid.webdav.HttpException;
@ -36,6 +38,7 @@ import at.bitfire.davdroid.webdav.WebDavResource.PutMode;
import ezvcard.io.text.VCardParseException;
import lombok.Cleanup;
import lombok.Getter;
import lombok.Setter;
/**
* Represents a remotely stored synchronizable collection (collection as in
@ -75,8 +78,28 @@ public abstract class RemoteCollection<T extends Resource> {
return collection.getCTag();
}
/**
* Returns a body for the REPORT request that queries all members of the collection
* that should be considered. Allows collections to implement remote filters.
* @return body for REPORT request or null if PROPFIND shall be used
*/
public String getMemberETagsQuery() {
return null;
}
/**
* Gets the ETags of the resources in a collection. If davQuery is set, it's required to be a
* complete addressbook-query or calendar-query XML and will cause getMemberETags() to use REPORT
* instead of PROPFIND.
* @return array of Resources where only the resource names and ETags are set
*/
public Resource[] getMemberETags() throws URISyntaxException, IOException, DavException, HttpException {
collection.propfind(HttpPropfind.Mode.MEMBERS_ETAG);
String query = getMemberETagsQuery();
if (query != null)
collection.report(query);
else
collection.propfind(HttpPropfind.Mode.MEMBERS_ETAG);
List<T> resources = new LinkedList<T>();
if (collection.getMembers() != null)
@ -84,13 +107,15 @@ public abstract class RemoteCollection<T extends Resource> {
resources.add(newResourceSkeleton(member.getName(), member.getETag()));
return resources.toArray(new Resource[0]);
}
@SuppressWarnings("unchecked")
public Resource[] multiGet(Resource[] resources) throws URISyntaxException, IOException, DavException, HttpException {
try {
if (resources.length == 1)
return (T[]) new Resource[]{get(resources[0])};
return (T[]) new Resource[] { get(resources[0]) };
Log.i(TAG, "Multi-getting " + resources.length + " remote resource(s)");

View file

@ -27,8 +27,8 @@ import at.bitfire.davdroid.resource.RemoteCollection;
public class CalendarsSyncAdapterService extends Service {
private static SyncAdapter syncAdapter;
@Override
public void onCreate() {
if (syncAdapter == null)
@ -48,7 +48,7 @@ public class CalendarsSyncAdapterService extends Service {
private static class SyncAdapter extends DavSyncAdapter {
private final static String TAG = "davdroid.CalendarsSyncAdapter";
private final static String TAG = "davdroid.CalDAVSync";
private SyncAdapter(Context context) {

View file

@ -47,7 +47,7 @@ public class ContactsSyncAdapterService extends Service {
private static class ContactsSyncAdapter extends DavSyncAdapter {
private final static String TAG = "davdroid.ContactsSyncAdapter";
private final static String TAG = "davdroid.CardDAVSync";
private ContactsSyncAdapter(Context context) {

View file

@ -0,0 +1,23 @@
package at.bitfire.davdroid.webdav;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.Namespace;
import org.simpleframework.xml.NamespaceList;
import org.simpleframework.xml.Root;
import lombok.Getter;
import lombok.Setter;
@Root(name="calendar-query")
@NamespaceList({
@Namespace(reference="DAV:"),
@Namespace(prefix="C",reference="urn:ietf:params:xml:ns:caldav")
})
@Namespace(prefix="C",reference="urn:ietf:params:xml:ns:caldav")
public class DavCalendarQuery {
@Element
@Getter @Setter DavProp prop;
@Element
@Getter @Setter DavFilter filter;
}

View file

@ -0,0 +1,23 @@
package at.bitfire.davdroid.webdav;
import org.simpleframework.xml.Attribute;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.Namespace;
import org.simpleframework.xml.Root;
import lombok.Getter;
import lombok.Setter;
@Namespace(prefix="C",reference="urn:ietf:params:xml:ns:caldav")
public class DavCompFilter {
public DavCompFilter(String name) {
this.name = name;
}
@Attribute(required=false)
String name;
@Element(required=false,name="comp-filter")
@Getter @Setter DavCompFilter compFilter;
}

View file

@ -0,0 +1,13 @@
package at.bitfire.davdroid.webdav;
import org.simpleframework.xml.Element;
import org.simpleframework.xml.Namespace;
import lombok.Getter;
import lombok.Setter;
@Namespace(prefix="C",reference="urn:ietf:params:xml:ns:caldav")
public class DavFilter {
@Element(required=false)
@Getter @Setter DavCompFilter compFilter;
}

View file

@ -35,7 +35,7 @@ public class DavProp {
GetCTag getctag;
@Element(required=false)
GetETag getetag;
@Setter GetETag getetag;
@Root(strict=false)
public static class ResourceType {

View file

@ -332,6 +332,18 @@ public class WebDavResource {
processMultiStatus(response);
}
public void report(String query) throws IOException, HttpException, DavException {
HttpReport report = new HttpReport(location, query);
report.setHeader("Depth", "1");
@Cleanup CloseableHttpResponse response = httpClient.execute(report, context);
if (response == null)
throw new DavNoContentException();
checkResponse(response);
processMultiStatus(response);
}
/* resource operations */