/*
* *
* 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;
import org.anhonesteffort.flock.util.guava.Optional;
import org.apache.commons.httpclient.Header;
import org.apache.jackrabbit.webdav.DavException;
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.PropFindMethod;
import org.apache.jackrabbit.webdav.property.DavProperty;
import org.apache.jackrabbit.webdav.property.DavPropertyNameSet;
import org.apache.jackrabbit.webdav.property.DavPropertySet;
import org.w3c.dom.Element;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.List;
/**
* Programmer: rhodey
*/
public abstract class AbstractDavComponentStore <C extends DavComponentCollection<?>>
implements DavComponentStore<C>
{
protected final String productId = "OpenWhisperSystems - Flock";
protected final String hostHREF;
protected final String username;
protected final String password;
protected Optional<String> currentUserPrincipal = Optional.absent();
protected DavClient davClient;
private Optional<List<String>> davOptions = Optional.absent();
public AbstractDavComponentStore(String hostHREF,
String username,
String password,
Optional<String> currentUserPrincipal)
throws DavException, IOException
{
this.hostHREF = hostHREF;
this.username = username;
this.password = password;
this.currentUserPrincipal = currentUserPrincipal;
this.davClient = new DavClient(new URL(hostHREF), username, password);
}
public AbstractDavComponentStore(DavClient client, Optional<String> currentUserPrincipal) {
this.davClient = client;
this.hostHREF = client.getDavHost().toString();
this.username = client.getUsername();
this.password = client.getPassword();
this.currentUserPrincipal = currentUserPrincipal;
}
public String getProductId() {
return productId;
}
@Override
public String getHostHREF() {
return hostHREF;
}
protected String getUserName() {
return username;
}
protected String getPassword() {
return password;
}
public DavClient getClient() {
return davClient;
}
public List<String> getDavOptions() throws DavException, IOException {
if (!davOptions.isPresent())
davOptions = Optional.of(davClient.getDavOptions());
return davOptions.get();
}
protected abstract String getWellKnownUri();
protected Optional<String> getCurrentUserPrincipalFromMultiStatus(MultiStatus multiStatus) {
for (MultiStatusResponse msResponse : multiStatus.getResponses()) {
DavPropertySet foundProperties = msResponse.getProperties(WebDavConstants.SC_OK);
DavProperty homeSetProperty = foundProperties.get(WebDavConstants.PROPERTY_NAME_CURRENT_USER_PRINCIPAL);
for (Status status : msResponse.getStatus()) {
if (status.getStatusCode() == WebDavConstants.SC_OK) {
if (homeSetProperty != null && homeSetProperty.getValue() instanceof ArrayList) {
for (Object child : (ArrayList<?>) homeSetProperty.getValue()) {
if (child instanceof Element) {
String currentUserPrincipalUri = ((Element) child).getTextContent();
if (!(currentUserPrincipalUri.endsWith("/")))
currentUserPrincipalUri = currentUserPrincipalUri.concat("/");
return Optional.of(currentUserPrincipalUri);
}
}
}
// Owncloud :(
else if (homeSetProperty != null && homeSetProperty.getValue() instanceof Element) {
String currentUserPrincipalUri = ((Element) homeSetProperty.getValue()).getTextContent();
if (!(currentUserPrincipalUri.endsWith("/")))
currentUserPrincipalUri = currentUserPrincipalUri.concat("/");
return Optional.of(currentUserPrincipalUri);
}
}
}
}
return Optional.absent();
}
protected Optional<String> getCurrentUserPrincipal(String propFindUri)
throws IOException, DavException
{
DavPropertyNameSet props = new DavPropertyNameSet();
props.add(WebDavConstants.PROPERTY_NAME_CURRENT_USER_PRINCIPAL);
PropFindMethod propFindMethod = new PropFindMethod(propFindUri,
props,
PropFindMethod.DEPTH_0);
try {
davClient.execute(propFindMethod);
return getCurrentUserPrincipalFromMultiStatus(propFindMethod.getResponseBodyAsMultiStatus());
} finally {
propFindMethod.releaseConnection();
}
}
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(getWellKnownUri());
PropFindMethod propFindMethod = new PropFindMethod(propFindUri,
props,
PropFindMethod.DEPTH_0);
try {
getClient().execute(propFindMethod);
return getCurrentUserPrincipalFromMultiStatus(propFindMethod.getResponseBodyAsMultiStatus());
} catch (DavException e) {
if (e.getErrorCode() == WebDavConstants.SC_MOVED_PERMANENTLY ||
e.getErrorCode() == WebDavConstants.SC_MOVED_TEMPORARILY ||
e.getErrorCode() == WebDavConstants.SC_SEE_OTHER ||
e.getErrorCode() == WebDavConstants.SC_USE_PROXY ||
e.getErrorCode() == WebDavConstants.SC_TEMPORARY_REDIRECT)
{
Header locationHeader = propFindMethod.getResponseHeader("location"); // TODO: find constant for this...
if (locationHeader.getValue() != null) {
currentUserPrincipal = getCurrentUserPrincipal(locationHeader.getValue());
return currentUserPrincipal;
}
}
else
throw e;
} finally {
propFindMethod.releaseConnection();
}
return Optional.absent();
}
@Override
public void removeCollection(String path) throws DavException, IOException {
DeleteMethod deleteMethod = new DeleteMethod(getHostHREF().concat(path));
try {
getClient().execute(deleteMethod);
if (!deleteMethod.succeeded() && deleteMethod.getStatusCode() != WebDavConstants.SC_OK)
throw new DavException(deleteMethod.getStatusCode(), deleteMethod.getStatusText());
} finally {
deleteMethod.releaseConnection();
}
}
@Override
public void closeHttpConnection() {
davClient.closeHttpConnection();
}
}