Java tutorial
/* * * * 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.webdav.caldav; import com.google.common.base.Optional; import org.anhonesteffort.flock.webdav.WebDavConstants; import org.anhonesteffort.flock.webdav.AbstractDavComponentStore; import org.anhonesteffort.flock.webdav.DavClient; import org.anhonesteffort.flock.webdav.DavComponentStore; import org.anhonesteffort.flock.webdav.ExtendedMkCol; import org.anhonesteffort.flock.webdav.PropertyParseException; import org.apache.commons.httpclient.Header; import org.apache.jackrabbit.webdav.DavConstants; import org.apache.jackrabbit.webdav.DavException; import org.apache.jackrabbit.webdav.DavServletResponse; import org.apache.jackrabbit.webdav.MultiStatus; import org.apache.jackrabbit.webdav.MultiStatusResponse; import org.apache.jackrabbit.webdav.Status; import org.apache.jackrabbit.webdav.client.methods.DeleteMethod; import org.apache.jackrabbit.webdav.client.methods.MkColMethod; import org.apache.jackrabbit.webdav.client.methods.PropFindMethod; import org.apache.jackrabbit.webdav.property.DavProperty; import org.apache.jackrabbit.webdav.property.DavPropertyName; import org.apache.jackrabbit.webdav.property.DavPropertyNameSet; import org.apache.jackrabbit.webdav.property.DavPropertySet; import org.apache.jackrabbit.webdav.property.DefaultDavProperty; import org.w3c.dom.Element; import org.w3c.dom.Node; import java.io.IOException; import java.util.ArrayList; import java.util.LinkedList; import java.util.List; /** * Programmer: rhodey */ public class CalDavStore extends AbstractDavComponentStore<CalDavCollection> implements DavComponentStore<CalDavCollection> { protected Optional<String> calendarHomeSet = Optional.absent(); public CalDavStore(String hostHREF, String username, String password, Optional<String> currentUserPrincipal, Optional<String> calendarHomeSet) throws DavException, IOException { super(hostHREF, username, password, currentUserPrincipal); this.calendarHomeSet = calendarHomeSet; } public CalDavStore(DavClient client, Optional<String> currentUserPrincipal, Optional<String> calendarHomeSet) { super(client, currentUserPrincipal); this.calendarHomeSet = calendarHomeSet; } @Override public Optional<String> getCurrentUserPrincipal() throws DavException, IOException { if (currentUserPrincipal.isPresent()) return currentUserPrincipal; DavPropertyNameSet props = new DavPropertyNameSet(); props.add(WebDavConstants.PROPERTY_NAME_CURRENT_USER_PRINCIPAL); String propFindUri = getHostHREF().concat("/.well-known/caldav"); PropFindMethod propFindMethod = new PropFindMethod(propFindUri, props, PropFindMethod.DEPTH_0); try { getClient().execute(propFindMethod); propFindMethod.getResponseBodyAsMultiStatus(); } catch (DavException e) { if (e.getErrorCode() == DavServletResponse.SC_MOVED_PERMANENTLY) { Header locationHeader = propFindMethod.getResponseHeader("location"); // TODO: find constant for this... if (locationHeader.getValue() != null) { currentUserPrincipal = super.getCurrentUserPrincipal(locationHeader.getValue()); return currentUserPrincipal; } } throw e; } finally { propFindMethod.releaseConnection(); } return Optional.absent(); } public Optional<String> getCalendarHomeSet() throws PropertyParseException, DavException, IOException { if (calendarHomeSet.isPresent()) return calendarHomeSet; if (!getCurrentUserPrincipal().isPresent()) throw new PropertyParseException("DAV:current-user-principal unavailable, server must support rfc5785.", getHostHREF(), WebDavConstants.PROPERTY_NAME_CURRENT_USER_PRINCIPAL); DavPropertyNameSet principalsProps = new DavPropertyNameSet(); principalsProps.add(CalDavConstants.PROPERTY_NAME_CALENDAR_HOME_SET); principalsProps.add(DavPropertyName.DISPLAYNAME); String propFindUri = getHostHREF().concat(getCurrentUserPrincipal().get()); PropFindMethod propFindMethod = new PropFindMethod(propFindUri, principalsProps, PropFindMethod.DEPTH_0); try { getClient().execute(propFindMethod); MultiStatus multiStatus = propFindMethod.getResponseBodyAsMultiStatus(); MultiStatusResponse[] msResponses = multiStatus.getResponses(); for (MultiStatusResponse msResponse : msResponses) { DavPropertySet foundProperties = msResponse.getProperties(DavServletResponse.SC_OK); DavProperty homeSetProperty = foundProperties.get(CalDavConstants.PROPERTY_NAME_CALENDAR_HOME_SET); for (Status status : msResponse.getStatus()) { if (status.getStatusCode() == DavServletResponse.SC_OK) { if (homeSetProperty != null && homeSetProperty.getValue() instanceof ArrayList) { for (Object child : (ArrayList<?>) homeSetProperty.getValue()) { if (child instanceof Element) { String calendarHomeSetUri = ((Element) child).getTextContent(); if (!(calendarHomeSetUri.endsWith("/"))) calendarHomeSetUri = calendarHomeSetUri.concat("/"); calendarHomeSet = Optional.of(calendarHomeSetUri); return calendarHomeSet; } } } // OwnCloud :( else if (homeSetProperty != null && homeSetProperty.getValue() instanceof Element) { String calendarHomeSetUri = ((Element) homeSetProperty.getValue()).getTextContent(); if (!(calendarHomeSetUri.endsWith("/"))) calendarHomeSetUri = calendarHomeSetUri.concat("/"); calendarHomeSet = Optional.of(calendarHomeSetUri); return calendarHomeSet; } } } } } finally { propFindMethod.releaseConnection(); } return Optional.absent(); } @Override public void addCollection(String path) throws DavException, IOException { addCollection(path, new DavPropertySet()); } public void addCollection(String path, DavPropertySet properties) throws DavException, IOException { ArrayList<DavPropertyName> resourceTypes = new ArrayList<DavPropertyName>(); resourceTypes.add(DavPropertyName.create(DavConstants.XML_COLLECTION, DavConstants.NAMESPACE)); resourceTypes.add(DavPropertyName.create("calendar", CalDavConstants.CALDAV_NAMESPACE)); // TODO: constant for this... properties.add( new DefaultDavProperty<ArrayList<DavPropertyName>>(DavPropertyName.RESOURCETYPE, resourceTypes)); MkColMethod mkColMethod = new MkColMethod(getHostHREF().concat(path)); ExtendedMkCol extendedMkCol = new ExtendedMkCol(properties); try { mkColMethod.setRequestBody(extendedMkCol); getClient().execute(mkColMethod); if (!mkColMethod.succeeded()) throw new DavException(mkColMethod.getStatusCode(), mkColMethod.getStatusText()); } finally { mkColMethod.releaseConnection(); } } public void addCollection(String path, String displayName, String description, int color) throws DavException, IOException { DavPropertySet properties = new DavPropertySet(); properties.add(new DefaultDavProperty<String>(DavPropertyName.DISPLAYNAME, displayName)); properties.add( new DefaultDavProperty<String>(CalDavConstants.PROPERTY_NAME_CALENDAR_DESCRIPTION, description)); properties.add(new DefaultDavProperty<Integer>(CalDavConstants.PROPERTY_NAME_CALENDAR_COLOR, color)); addCollection(path, properties); } // TODO: I don't like this... public static List<CalDavCollection> getCollectionsFromMultiStatusResponses(CalDavStore store, MultiStatusResponse[] msResponses) { List<CalDavCollection> collections = new LinkedList<CalDavCollection>(); for (MultiStatusResponse msResponse : msResponses) { DavPropertySet foundProperties = msResponse.getProperties(DavServletResponse.SC_OK); String collectionUri = msResponse.getHref(); for (Status status : msResponse.getStatus()) { if (status.getStatusCode() == DavServletResponse.SC_OK) { boolean isCalendarCollection = false; DavPropertySet collectionProperties = new DavPropertySet(); DavProperty resourceTypeProperty = foundProperties.get(DavPropertyName.RESOURCETYPE); if (resourceTypeProperty != null) { Object resourceTypeValue = resourceTypeProperty.getValue(); if (resourceTypeValue instanceof ArrayList) { for (Node child : (ArrayList<Node>) resourceTypeValue) { if (child instanceof Element) { String localName = child.getLocalName(); if (localName != null) { isCalendarCollection = localName .equals(CalDavConstants.RESOURCE_TYPE_CALENDAR) || localName .equals(CalDavConstants.RESOURCE_TYPE_CALENDAR_PROXY_READ) || localName .equals(CalDavConstants.RESOURCE_TYPE_CALENDAR_PROXY_WRITE); } } } } } if (isCalendarCollection) { for (DavProperty property : foundProperties) { if (property != null) collectionProperties.add(property); } collections.add(new CalDavCollection(store, collectionUri, collectionProperties)); } } } } return collections; } @Override public Optional<CalDavCollection> getCollection(String path) throws DavException, IOException { CalDavCollection targetCollection = new CalDavCollection(this, path); DavPropertyNameSet collectionProps = targetCollection.getPropertyNamesForFetch(); PropFindMethod propFindMethod = new PropFindMethod(path, collectionProps, PropFindMethod.DEPTH_0); try { getClient().execute(propFindMethod); MultiStatus multiStatus = propFindMethod.getResponseBodyAsMultiStatus(); MultiStatusResponse[] responses = multiStatus.getResponses(); List<CalDavCollection> returnedCollections = getCollectionsFromMultiStatusResponses(this, responses); if (returnedCollections.size() == 0) Optional.absent(); return Optional.of(returnedCollections.get(0)); } catch (DavException e) { if (e.getErrorCode() == DavServletResponse.SC_NOT_FOUND) return Optional.absent(); throw e; } finally { propFindMethod.releaseConnection(); } } @Override public List<CalDavCollection> getCollections() throws PropertyParseException, DavException, IOException { Optional<String> calHomeSetUri = getCalendarHomeSet(); if (!calHomeSetUri.isPresent()) throw new PropertyParseException("No calendar-home-set property found for user.", getHostHREF(), CalDavConstants.PROPERTY_NAME_CALENDAR_HOME_SET); CalDavCollection hack = new CalDavCollection(this, ""); DavPropertyNameSet calendarProps = hack.getPropertyNamesForFetch(); PropFindMethod method = new PropFindMethod(getHostHREF().concat(calHomeSetUri.get()), calendarProps, PropFindMethod.DEPTH_1); try { getClient().execute(method); MultiStatus multiStatus = method.getResponseBodyAsMultiStatus(); MultiStatusResponse[] responses = multiStatus.getResponses(); return getCollectionsFromMultiStatusResponses(this, responses); } finally { method.releaseConnection(); } } @Override public void removeCollection(String path) throws DavException, IOException { DeleteMethod deleteMethod = new DeleteMethod(getHostHREF().concat(path)); try { getClient().execute(deleteMethod); if (!deleteMethod.succeeded()) throw new DavException(deleteMethod.getStatusCode(), deleteMethod.getStatusText()); } finally { deleteMethod.releaseConnection(); } } }