at.bitfire.davdroid.webdav.WebDavCollection.java Source code

Java tutorial

Introduction

Here is the source code for at.bitfire.davdroid.webdav.WebDavCollection.java

Source

/*******************************************************************************
 * Copyright (c) 2013 Richard 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 java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.StringWriter;
import java.net.URI;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;

import lombok.Getter;

import org.apache.commons.io.input.TeeInputStream;
import org.apache.http.HttpException;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.StatusLine;
import org.apache.http.message.BasicLineParser;
import org.simpleframework.xml.Serializer;
import org.simpleframework.xml.core.Persister;

import android.util.Log;
import at.bitfire.davdroid.resource.IncapableResourceException;

public class WebDavCollection extends WebDavResource {
    private static final String TAG = "davdroid.WebDavCollection";

    public enum MultigetType {
        ADDRESS_BOOK, CALENDAR
    }

    /* list of resource members, null until filled by propfind() or multiGet() */
    @Getter
    protected List<WebDavResource> members;

    public WebDavCollection(URI baseURL, String username, String password, boolean preemptiveAuth)
            throws IOException {
        super(baseURL, username, password, preemptiveAuth);
    }

    public WebDavCollection(WebDavCollection parent, URI member) {
        super(parent, member);
    }

    public WebDavCollection(WebDavCollection parent, String member) {
        super(parent, member);
    }

    /* collection operations */

    public boolean propfind(HttpPropfind.Mode mode) throws IOException, IncapableResourceException, HttpException {
        HttpPropfind propfind = new HttpPropfind(location, mode);
        HttpResponse response = client.execute(propfind);
        checkResponse(response);

        if (response.getStatusLine().getStatusCode() == HttpStatus.SC_MULTI_STATUS) {
            DavMultistatus multistatus;
            try {
                Serializer serializer = new Persister();
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                InputStream is = new TeeInputStream(response.getEntity().getContent(), baos);
                multistatus = serializer.read(DavMultistatus.class, is);

                Log.d(TAG, "Received multistatus response: " + baos.toString("UTF-8"));
            } catch (Exception e) {
                Log.w(TAG, e);
                throw new IncapableResourceException();
            }
            processMultiStatus(multistatus);
            return true;

        } else
            return false;
    }

    public boolean multiGet(String[] names, MultigetType type)
            throws IOException, IncapableResourceException, HttpException {
        DavMultiget multiget = (type == MultigetType.ADDRESS_BOOK) ? new DavAddressbookMultiget()
                : new DavCalendarMultiget();

        multiget.prop = new DavProp();
        multiget.prop.getetag = new DavProp.DavPropGetETag();

        if (type == MultigetType.ADDRESS_BOOK)
            multiget.prop.addressData = new DavProp.DavPropAddressData();
        else if (type == MultigetType.CALENDAR)
            multiget.prop.calendarData = new DavProp.DavPropCalendarData();

        multiget.hrefs = new ArrayList<DavHref>(names.length);
        for (String name : names)
            multiget.hrefs.add(new DavHref(location.resolve(name).getPath()));

        Serializer serializer = new Persister();
        StringWriter writer = new StringWriter();
        try {
            serializer.write(multiget, writer);
        } catch (Exception e) {
            Log.e(TAG, e.getLocalizedMessage());
            return false;
        }

        HttpReport report = new HttpReport(location, writer.toString());
        HttpResponse response = client.execute(report);
        checkResponse(response);

        if (response.getStatusLine().getStatusCode() == HttpStatus.SC_MULTI_STATUS) {
            DavMultistatus multistatus;
            try {
                ByteArrayOutputStream baos = new ByteArrayOutputStream();
                InputStream is = new TeeInputStream(response.getEntity().getContent(), baos);
                multistatus = serializer.read(DavMultistatus.class, is);

                Log.d(TAG, "Received multistatus response: " + baos.toString("UTF-8"));
            } catch (Exception e) {
                Log.e(TAG, e.getLocalizedMessage());
                return false;
            }
            processMultiStatus(multistatus);

        } else
            throw new IncapableResourceException();
        return true;
    }

    /* member operations */

    @Override
    public void put(byte[] data, PutMode mode) throws IOException, HttpException {
        properties.remove(Property.CTAG);
        super.put(data, mode);
    }

    @Override
    public void delete() throws IOException, HttpException {
        properties.remove(Property.CTAG);
        super.delete();
    }

    /* HTTP support */

    protected void processMultiStatus(DavMultistatus multistatus) throws HttpException {
        List<WebDavResource> members = new LinkedList<WebDavResource>();

        if (multistatus.response == null) // empty response
            return;

        for (DavResponse singleResponse : multistatus.response) {
            String href = singleResponse.getHref().href;

            for (DavPropstat singlePropstat : singleResponse.getPropstat()) {
                StatusLine status = BasicLineParser.parseStatusLine(singlePropstat.status, new BasicLineParser());

                try {
                    checkResponse(status);
                } catch (NotFoundException e) {
                    continue;
                }

                WebDavResource referenced = null;

                if (location.equals(location.resolve(href))) {
                    // response is about this property
                    referenced = this;

                } else {
                    // response is about a member, add it
                    URI uri = location.resolve(href);
                    referenced = new WebDavResource(this, uri);
                    members.add(referenced);
                }

                DavProp prop = singlePropstat.prop;

                if (prop.currentUserPrincipal != null)
                    referenced.properties.put(Property.CURRENT_USER_PRINCIPAL,
                            prop.currentUserPrincipal.getHref().href);

                if (prop.addressbookHomeSet != null)
                    referenced.properties.put(Property.ADDRESSBOOK_HOMESET, prop.addressbookHomeSet.getHref().href);

                if (singlePropstat.prop.calendarHomeSet != null)
                    referenced.properties.put(Property.CALENDAR_HOMESET, prop.calendarHomeSet.getHref().href);

                if (prop.displayname != null)
                    referenced.properties.put(Property.DISPLAY_NAME, prop.displayname.getDisplayName());

                if (prop.resourcetype != null) {
                    if (prop.resourcetype.getAddressbook() != null) {
                        referenced.properties.put(Property.IS_ADDRESSBOOK, "1");

                        if (prop.addressbookDescription != null)
                            referenced.properties.put(Property.DESCRIPTION,
                                    prop.addressbookDescription.getDescription());
                    } else
                        referenced.properties.remove(Property.IS_ADDRESSBOOK);

                    if (prop.resourcetype.getCalendar() != null) {
                        referenced.properties.put(Property.IS_CALENDAR, "1");

                        if (prop.calendarDescription != null)
                            referenced.properties.put(Property.DESCRIPTION,
                                    prop.calendarDescription.getDescription());
                    } else
                        referenced.properties.remove(Property.IS_CALENDAR);
                }

                if (prop.getctag != null)
                    referenced.properties.put(Property.CTAG, prop.getctag.getCTag());

                if (prop.getetag != null)
                    referenced.properties.put(Property.ETAG, prop.getetag.getETag());

                if (prop.calendarData != null)
                    referenced.content = new ByteArrayInputStream(prop.calendarData.ical.getBytes());
                else if (prop.addressData != null)
                    referenced.content = new ByteArrayInputStream(prop.addressData.vcard.getBytes());
            }
        }
        this.members = members;
    }
}