/*
* Copyright (C) 2015, Martin Goellnitz
*
* 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 2 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, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301, USA
*/
package jfs.sync.util;
import com.github.sardine.DavResource;
import com.github.sardine.Sardine;
import java.io.IOException;
import java.text.DateFormat;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.HashSet;
import java.util.List;
import java.util.Locale;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import javax.xml.namespace.QName;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* Some common utility functions for the access of WebDAV resources through Sardine.
*/
public final class DavUtils {
public static final String PROP_LAST_MODIFIED_TIME_WIN = "Win32LastModifiedTime";
public static final QName QNAME_LAST_MODIFIED_TIME_WIN = new QName("urn:schemas-microsoft-com:", PROP_LAST_MODIFIED_TIME_WIN, "ns1");
public static final String PROP_LAST_MODIFIED_TIME = "getlastmodified";
public static final String PROP_CUSTOM_MODIFIED = "JFileSync";
public static final QName QNAME_LAST_MODIFIED_TIME = new QName("DAV:", PROP_LAST_MODIFIED_TIME, "d");
public static final QName QNAME_CUSTOM_MODIFIED = new QName("http://www.provocon.de/sync", PROP_CUSTOM_MODIFIED, "sync");
private static final DateFormat DATE_FORMAT;
private static final Logger LOG = LoggerFactory.getLogger(DavUtils.class);
private static final Set<QName> CUSTOM_PROPS = new HashSet<>();
static {
CUSTOM_PROPS.add(DavUtils.QNAME_CUSTOM_MODIFIED);
CUSTOM_PROPS.add(DavUtils.QNAME_LAST_MODIFIED_TIME_WIN);
DATE_FORMAT = new SimpleDateFormat("EEE, d MMM yyyy HH:mm:ss z", Locale.ROOT);
DATE_FORMAT.setTimeZone(TimeZone.getTimeZone("GMT"));
}
private DavUtils() {
}
public static Set<QName> getCustomDavProperties() {
return CUSTOM_PROPS;
} // getCustomDavProperties()
public static long getModificationDate(DavResource resource) {
Date modificationDate = resource.getModified();
String modifiedDateString = resource.getCustomProps().get(DavUtils.PROP_LAST_MODIFIED_TIME_WIN);
LOG.info("getModificationDate() custom properties for {}: {}", resource.getName(), resource.getCustomPropsNS());
if (StringUtils.isNotEmpty(modifiedDateString)) {
try {
synchronized (DATE_FORMAT) {
modificationDate = DATE_FORMAT.parse(modifiedDateString);
}
} catch (ParseException pe) {
LOG.error("createFileInfo() {}", pe.getMessage());
} catch (Exception e) {
LOG.error("createFileInfo()", e);
} // try/catch
} // if
LOG.debug("getModificationDate() {} [{};{}]", modificationDate.getTime(), modificationDate, resource.getModified().getTime());
return modificationDate.getTime();
} // getModificationDate()
/**
* Set or modify a property.
*
* @param sardine Sardine instance to use
* @param url Specification of the resource to set the value for
* @param property qualified property name with namespace
* @param value new property value
* @return true if setting of property was succesful
*/
private static boolean setProperty(Sardine sardine, String url, QName property, String value) {
boolean success = false;
// List<QName> removeProps = new ArrayList<>(1);
// removeProps.add(property);
Set<QName> props = new HashSet<>(1);
props.add(property);
Map<QName, String> addProps = new HashMap<>();
addProps.put(property, value);
try {
List<DavResource> result = sardine.patch(url, addProps);
LOG.info("setProperty() result list size {}", result.size());
success = (result.size()==1);
if (success) {
result = sardine.list(url, 1, props);
LOG.info("setProperty() result custom props {}", result.get(0).getCustomPropsNS());
} // if
} catch (IOException e) {
LOG.error("setProperty() failed for "+url, e);
} // try/catch
return success;
} // setProperty()
/**
* Set modification time for a given resource.
* This method tries to set the modification date and a second custom flag like it's used
* by the windows explorer.
*
* @param access Sardine instance to use.
* @param url url of the resource to set the modification time for.
* @param time modification time in seconds since the epoche
* @return return if operation was successul
*/
public static boolean setLastModified(Sardine access, String url, long time) {
String modificationDate;
synchronized (DATE_FORMAT) {
modificationDate = DATE_FORMAT.format(new Date(time));
}
LOG.debug("setLastModified() setting time for {} to {}", url, modificationDate);
boolean success = DavUtils.setProperty(access, url, DavUtils.QNAME_LAST_MODIFIED_TIME_WIN, modificationDate);
// success = success&DavUtils.setProperty(access, url, DavUtils.QNAME_LAST_MODIFIED_TIME, modificationDate);
// success = success&DavUtils.setProperty(access, url, DavUtils.QNAME_CUSTOM_MODIFIED, modificationDate);
return success;
} // setLastModified()
} // DavUtils