From 46b61a132404871b36a89a6615d27e2bc24bc616 Mon Sep 17 00:00:00 2001 From: Mathew McBride Date: Sun, 23 Nov 2008 11:11:45 +1100 Subject: [PATCH] Whoops, lets try again, Big big update. Allow SSL connections to server without certificate installed, fix SAXDAVHandler so it detects item type correctly, cleanup groupDAV, use native SQL TIMESTAMP type, and more --- .../bionicmessage/groupdav/CalDAVExtensions.java | 11 +- .../bionicmessage/groupdav/CardDAVExtensions.java | 16 +- .../java/net/bionicmessage/groupdav/Common.java | 73 +++++-- .../groupdav/ConcurrentDownloader.java | 12 +- .../net/bionicmessage/groupdav/SAXDAVHandler.java | 4 +- .../java/net/bionicmessage/groupdav/groupDAV.java | 218 +++++++-------------- .../MultipleSourceICalendarObjectStore.java | 182 +++++++++-------- .../objects/MultipleSourceObjectTracking.java | 78 +++++--- .../objects/MultipleSourceVCardObjectStore.java | 59 +++--- src/test/java/CalDAVExtensions.java | 25 +-- .../MultipleSourceICalendarObjectStoreTest.java | 2 +- ...MultipleSourceICalendarObjectStoreTodoTest.java | 2 +- src/test/java/groupdavTest.java | 7 + 13 files changed, 347 insertions(+), 342 deletions(-) diff --git a/src/main/java/net/bionicmessage/groupdav/CalDAVExtensions.java b/src/main/java/net/bionicmessage/groupdav/CalDAVExtensions.java index 6f4935c..ea51d84 100644 --- a/src/main/java/net/bionicmessage/groupdav/CalDAVExtensions.java +++ b/src/main/java/net/bionicmessage/groupdav/CalDAVExtensions.java @@ -147,8 +147,7 @@ public class CalDAVExtensions implements IDAVHandler,ServerDriver { } public boolean doesSupportCalDAV(URL fullURL) - throws UnsupportedEncodingException, - IOException { + throws Exception { // Build an OPTIONS query byte[] query = Common.buildQuery("OPTIONS", fullURL, new byte[0], null, base64cache); String response = Common.sendNonKeepAliveRequest(davServer, query, base64cache, log); @@ -158,8 +157,7 @@ public class CalDAVExtensions implements IDAVHandler,ServerDriver { } public void doBasicReport(URL fullURL) - throws UnsupportedEncodingException, - IOException { + throws Exception { byte[] query = Common.buildQuery("REPORT", fullURL, new byte[0], null, base64cache); String response = Common.sendNonKeepAliveRequest(davServer, query, base64cache, log); GroupDAVObject rbo = new GroupDAVObject(response, GroupDAVObject.OBJECT_GET); @@ -183,10 +181,7 @@ public class CalDAVExtensions implements IDAVHandler,ServerDriver { String type, String param1, String param2) - throws UnsupportedEncodingException, - IOException, - SAXException, - XPathExpressionException { + throws Exception { /* String query = String.format(CALDAV_DISCOVER_BY_TIME, iComponent, type, diff --git a/src/main/java/net/bionicmessage/groupdav/CardDAVExtensions.java b/src/main/java/net/bionicmessage/groupdav/CardDAVExtensions.java index bd1a870..8ba83d6 100644 --- a/src/main/java/net/bionicmessage/groupdav/CardDAVExtensions.java +++ b/src/main/java/net/bionicmessage/groupdav/CardDAVExtensions.java @@ -89,8 +89,8 @@ public class CardDAVExtensions implements IDAVHandler,ServerDriver { query, base64cache, Logger.getLogger("bsh")); - GroupDAVObject gbo = new GroupDAVObject(resp); - return extractFromReport(gbo, new ArrayList()); + HTTPInputStream in = Common.sendNonKeepAliveRequest(url, query); + return extractFromReport(in, new ArrayList()); } public List doMultiget(URL root, List toDownload, List addTo) throws Exception { StringBuffer reportRequest = new StringBuffer(""); @@ -106,18 +106,16 @@ public class CardDAVExtensions implements IDAVHandler,ServerDriver { HashMap headers = new HashMap(); headers.put("Depth","1"); byte[] query = Common.buildQuery("REPORT", root, reportRequest.toString().getBytes("UTF-8"), headers, base64cache); - String resp = Common.sendNonKeepAliveRequest(server, query, base64cache, log); - GroupDAVObject gbo = new GroupDAVObject(resp); - return extractFromReport(gbo,addTo); + HTTPInputStream his = Common.sendNonKeepAliveRequest(server, query); + return extractFromReport(his, addTo); } - protected List extractFromReport(GroupDAVObject report, List addTo) throws Exception { - StringReader sr = new StringReader(report.getContent()); + protected List extractFromReport(HTTPInputStream in, List addTo) throws Exception { ready = false; retException = null; XMLReader parser = XMLReaderFactory.createXMLReader(); SAXDAVHandler ceh = new SAXDAVHandler(this); parser.setContentHandler(ceh); - parser.parse(new InputSource(sr)); + parser.parse(new InputSource(in)); do { // wait } while (!ready); //wait for XML parser @@ -133,7 +131,7 @@ public class CardDAVExtensions implements IDAVHandler,ServerDriver { URL modifiedHref = new URL(server, href); String etag = etagsStack.pop(); String contents = contentsStack.pop(); - GroupDAVObject child = new GroupDAVObject(report, contents, etag, modifiedHref.toExternalForm()); + GroupDAVObject child = new GroupDAVObject(in, contents, etag, modifiedHref.toExternalForm()); addTo.add(child); } return addTo; diff --git a/src/main/java/net/bionicmessage/groupdav/Common.java b/src/main/java/net/bionicmessage/groupdav/Common.java index 54f76c7..84d45bd 100644 --- a/src/main/java/net/bionicmessage/groupdav/Common.java +++ b/src/main/java/net/bionicmessage/groupdav/Common.java @@ -36,6 +36,11 @@ import java.net.URL; import java.util.Iterator; import java.util.Map; import java.util.logging.Logger; +import javax.net.SocketFactory; +import javax.net.ssl.SSLContext; +import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; /** * @@ -43,6 +48,25 @@ import java.util.logging.Logger; */ public class Common { + static SocketFactory ssf = null; + public static // Create a trust manager that does not validate certificate chains + TrustManager[] trustAllCerts = new TrustManager[]{ + new X509TrustManager() { + + public java.security.cert.X509Certificate[] getAcceptedIssuers() { + return null; + } + + public void checkClientTrusted( + java.security.cert.X509Certificate[] certs, String authType) { + } + + public void checkServerTrusted( + java.security.cert.X509Certificate[] certs, String authType) { + } + } + }; + public static byte[] buildQuery(String method, URL fullURL, byte[] data, @@ -81,6 +105,7 @@ public class Common { System.arraycopy(data, 0, fulldata, headers_content.length, data.length); return fulldata; } + public static URL createURL(String path, URL serverURL) throws MalformedURLException { String newPath = path; @@ -88,37 +113,63 @@ public class Common { return new URL(path); } // Don't muck with full URLs // Clean path of: leading slash, etc. + if (path.startsWith("/")) { newPath = path.substring(1); } newPath = newPath.replace("//", "/"); return new URL(serverURL, newPath); } + + public static Socket createSocket(URL url) throws Exception { + int port = url.getPort(); + if (url.getProtocol().contains("https")) { + if (port == -1) { + port = 443; + } + if (ssf == null) { + try { + SSLContext sc = SSLContext.getInstance("SSL"); + sc.init(null, Common.trustAllCerts, new java.security.SecureRandom()); + ssf = sc.getSocketFactory(); + } catch (Exception e) { + System.err.println("Error configuration SSL cert manager"); + e.printStackTrace(); + } + } + return ssf.createSocket(url.getHost(), port); + } else { + if (port == -1) { + port = 80; + } + return new Socket(url.getHost(), port); + } + } + public static HTTPInputStream sendNonKeepAliveRequest(URL srv, byte[] data) throws Exception { - int port = srv.getPort(); - if (port == -1) - port = 80; - Socket st = new Socket(srv.getHost(),port); + int port = srv.getPort(); + if (port == -1) { + port = 80; + } + Socket st = createSocket(srv); st.getOutputStream().write(data); HTTPInputStream is = new HTTPInputStream(st); - return is; + return is; } + public static String sendNonKeepAliveRequest( URL server, byte[] by, String base64cache, - Logger l) throws IOException { + Logger l) throws Exception { String dbugstring = new String(by); String loggableString = dbugstring.replace(base64cache, "Authorization: Basic [removed]"); l.fine("We sent:\r\n" + loggableString); // Measure latency long time = new java.util.Date().getTime(); - int port = server.getPort(); - if (port == -1) { - port = 80; - } - Socket st = new Socket(server.getHost(), port); + Socket st = createSocket(server); + st.setSoTimeout(15*1000); st.getOutputStream().write(by); st.getOutputStream().flush(); InputStream sc = st.getInputStream(); diff --git a/src/main/java/net/bionicmessage/groupdav/ConcurrentDownloader.java b/src/main/java/net/bionicmessage/groupdav/ConcurrentDownloader.java index 38571dd..b73303e 100644 --- a/src/main/java/net/bionicmessage/groupdav/ConcurrentDownloader.java +++ b/src/main/java/net/bionicmessage/groupdav/ConcurrentDownloader.java @@ -22,6 +22,7 @@ */ package net.bionicmessage.groupdav; +import java.util.List; import java.util.Stack; /** @@ -32,23 +33,24 @@ import java.util.Stack; public class ConcurrentDownloader { private Stack urlsToDownload; - private Stack downloadedObjects; + private List downloadedObjects; private groupDAV client; private int numOfWorkers = 1; private int downloadedObjs = 0; private DownloadWorker[] workers; - + public ConcurrentDownloader(groupDAV client) { this.client = client; urlsToDownload = new Stack(); - downloadedObjects = new Stack(); } public void addURLToDownload(String url) { urlsToDownload.push(url); } - public Stack downloadObjects() { + public List downloadObjects(List toAdd, int numOfWorkers) { + downloadedObjects = toAdd; + this.numOfWorkers = numOfWorkers; workers = new DownloadWorker[numOfWorkers]; int objsToDownload = urlsToDownload.size(); for (int i = 0; i < workers.length; i++) { @@ -74,7 +76,7 @@ public class ConcurrentDownloader { } protected synchronized void finishedDownloading(GroupDAVObject obj) { - downloadedObjects.push(obj); + downloadedObjects.add(obj); downloadedObjs++; } diff --git a/src/main/java/net/bionicmessage/groupdav/SAXDAVHandler.java b/src/main/java/net/bionicmessage/groupdav/SAXDAVHandler.java index ce8cf00..b9d1d15 100644 --- a/src/main/java/net/bionicmessage/groupdav/SAXDAVHandler.java +++ b/src/main/java/net/bionicmessage/groupdav/SAXDAVHandler.java @@ -93,9 +93,9 @@ public class SAXDAVHandler extends DefaultHandler { } contents.push(ch); } - if (localName.contains("collection")) { + if (localName.contains("collection") && uri.contains("groupdav.org")) { types.push(localName); - } else { + } else if (localName.contains("getcontenttype")) { types.push("obj"); } super.endElement(uri, localName, qName); diff --git a/src/main/java/net/bionicmessage/groupdav/groupDAV.java b/src/main/java/net/bionicmessage/groupdav/groupDAV.java index bc91f73..bc70e02 100644 --- a/src/main/java/net/bionicmessage/groupdav/groupDAV.java +++ b/src/main/java/net/bionicmessage/groupdav/groupDAV.java @@ -32,7 +32,10 @@ import java.util.logging.*; import javax.xml.parsers.*; import org.xml.sax.InputSource; import javax.net.SocketFactory; +import javax.net.ssl.SSLContext; import javax.net.ssl.SSLSocketFactory; +import javax.net.ssl.TrustManager; +import javax.net.ssl.X509TrustManager; /** * A basic GroupDAV implementation @@ -68,6 +71,7 @@ public class groupDAV implements IDAVHandler { private boolean propReady = false; private Exception propRetException = null; + /** For use in situations where something (i.e in the case of * Funambol's authentication) has already given us a HTTP Basic Base64 * representation of user:pass @@ -78,31 +82,8 @@ public class groupDAV implements IDAVHandler { * (Google HTTP Basic authentication for more information) */ public groupDAV(String url, String b64cache) { - origurl = url; - try { - serverURL = new URL(url); - if (serverURL.getProtocol().contains("https")) { - ssl = true; - } - tok = "https://"; - host = serverURL.getHost(); - po = serverURL.getPort(); - if (po == -1) { - po = 80; - } - } catch (MalformedURLException ex) { - Logger.getLogger(groupDAV.class.getName()).log(Level.SEVERE, null, ex); - throw new IllegalArgumentException(ex); - } - if (!origurl.substring(origurl.length() - 1).equals("/")) { - origurl = url + "/"; - } - if (url.indexOf("https://") != -1) { - ssl = true; - tok = "https://"; - } base64cache = "Authorization: Basic " + b64cache; - init(); + init(url); } /** Constructor using a http://// url, and plain text passwords. @@ -112,17 +93,32 @@ public class groupDAV implements IDAVHandler { * @param pass The password of the user connecting to the server */ public groupDAV(String url, String user, String pass) { + base64cache = "Authorization: Basic " + Base64.encodeBytes(new String(user + ":" + pass).getBytes()); + init(url); + } + + /** Set the logger to output to + * @param log The logger instance to use + */ + public void setLogger(Logger log) { + logger = log; + cdavex.setLog(log); + } + + /** Initiate client */ + public void init(String url) { origurl = url; try { serverURL = new URL(url); if (serverURL.getProtocol().contains("https")) { ssl = true; - tok = "https://"; } host = serverURL.getHost(); po = serverURL.getPort(); - if (po == -1) { + if (po == -1 && !ssl) { po = 80; + } else if (po == -1 && ssl) { + po = 443; } } catch (MalformedURLException ex) { Logger.getLogger(groupDAV.class.getName()).log(Level.SEVERE, null, ex); @@ -131,30 +127,15 @@ public class groupDAV implements IDAVHandler { if (!origurl.substring(origurl.length() - 1).equals("/")) { origurl = url + "/"; } - if (url.indexOf("https://") != -1) { - ssl = true; - tok = "https://"; - } - base64cache = "Authorization: Basic " + Base64.encodeBytes(new String(user + ":" + pass).getBytes()); - init(); - } - - /** Set the logger to output to - * @param log The logger instance to use - */ - public void setLogger(Logger log) { - logger = log; - cdavex.setLog(log); - } - - /** Initiate client */ - public void init() { logger.setLevel(Level.ALL); logger.addHandler(ch); ch.setLevel(Level.ALL); logger.info("GroupDAV client init()"); - ssf = SSLSocketFactory.getDefault(); - + try { + ssf = SSLSocketFactory.getDefault(); + } catch (Exception e) { + e.printStackTrace(); + } cdavex = new CalDAVExtensions(serverURL, base64cache, logger); cardex = new CardDAVExtensions(serverURL, base64cache, logger); cd = new ConcurrentDownloader(this); @@ -208,6 +189,7 @@ public class groupDAV implements IDAVHandler { /** List objects in a store */ public List listObjects(String url) throws Exception { + logger.fine("Listing objects for: " + url); byte[] pfind = buildPROPFIND(url); HTTPInputStream istream = Common.sendNonKeepAliveRequest(serverURL, pfind); InputSource is = new InputSource(istream); @@ -227,12 +209,14 @@ public class groupDAV implements IDAVHandler { String lurl = (String) urls.get(i); String type = (String) types.get(i); String etag = (String) etags.get(lurl); - if (type != null && type.contains("collection") | etag.length() < 1) { + if (type != null && type.contains("collection") || etag.length() < 1) { /* Don't add this location to the list; it is a collection */ + logger.finer("Collection: "+lurl); } else { // Make sure all URLs coming out of here are FULL! URL fullURL = Common.createURL(lurl, serverURL); cleaned.add(fullURL.toString()); + logger.finer("Object: "+fullURL.toExternalForm()); } } return cleaned; @@ -258,7 +242,7 @@ public class groupDAV implements IDAVHandler { byte[] query = Common.buildQuery("PUT", fullURL, contents.getBytes(), headers, base64cache); String q = new String(query); - String t = sendNonKeepAliveRequest(query); + String t = Common.sendNonKeepAliveRequest(serverURL, query, base64cache, logger); logger.fine("We got" + t); String firstLine = t.split("\r\n")[0]; if (firstLine.indexOf("405") != -1) { @@ -307,12 +291,14 @@ public class groupDAV implements IDAVHandler { headers.put("If-Match", etag); byte[] query = Common.buildQuery("PUT", objAddr, contents.getBytes("UTF-8"), headers, base64cache); String q = new String(query); - String resp = sendNonKeepAliveRequest(query); + String resp = Common.sendNonKeepAliveRequest(serverURL, query, base64cache, logger); logger.finest("We got: " + resp); String firstLine = resp.split("\r\n")[0]; GroupDAVObject gobjP = new GroupDAVObject(resp, GroupDAVObject.OBJECT_PUT); - if (gobjP.getStatus() > 400) { + if (gobjP.getStatus() > 400 && gobjP.getStatus() != 403) { // let 403 errors slide throw new Exception("Error modifying object: " + firstLine); + } else if (gobjP.getStatus() == 403) { + return null; // Forbidden errors should be dealt with by the user. } /* Did the server give us a location? If not, assume the location is exactly * what we gave it */ @@ -337,7 +323,7 @@ public class groupDAV implements IDAVHandler { HashMap header = new HashMap(); header.put("If-Match", etag); byte[] query = Common.buildQuery("DELETE", netURL, new byte[0], header, base64cache); - String resp = sendNonKeepAliveRequest(query); + String resp = Common.sendNonKeepAliveRequest(serverURL, query, base64cache, logger); logger.finest("We got: " + resp); GroupDAVObject gbo = new GroupDAVObject(resp, GroupDAVObject.OBJECT_KILLED); return gbo; @@ -350,12 +336,12 @@ public class groupDAV implements IDAVHandler { String header[] = {base64cache}; byte[] send = Common.buildQuery("GET", pathURL, new byte[0], null, base64cache); String st = new String(send); - String t = sendNonKeepAliveRequest(send); + String t = Common.sendNonKeepAliveRequest(serverURL, send, base64cache, logger); String firstLine = t.split("\r\n")[0]; - if (firstLine.contains("400")) { - throw new Exception("HTTP Exception encountered in getObject: " + firstLine); - } GroupDAVObject obj = new GroupDAVObject(t, GroupDAVObject.OBJECT_GET); + if (obj.getStatus() > 400) { + throw new Exception("HTTP error encountered: "+firstLine); + } obj.setLocation(pathURL.toExternalForm()); return obj; } @@ -371,57 +357,64 @@ public class groupDAV implements IDAVHandler { } /** Obtain all objects from a server store */ - public List getAllObjectsInPath(String path, int typeOfQuery) + public List getAllObjectsInPath(String path, int typeOfQuery, int downloadParameter) throws Exception { List toDL = this.listObjects(path); - return getObjectsInBulk(path, toDL, typeOfQuery); + return getObjectsInBulk(path, toDL,typeOfQuery,downloadParameter); } - /** Download objects in bulk using a two-thread downloader */ - public List getObjectsInBulk(String root, List paths, int typeOfQuery) throws Exception { + /** Download objects in bulk. + * @param root The root dir to get all objects from (i.e /groupdav/Calendar/) + * @param paths A list of objects to download + * @param typeOfQuery Server type + * @param downloadParamater Paramater for download driver + */ + public List getObjectsInBulk(String root, + List paths, + int typeOfQuery, + int downloadParameter) throws Exception { URL path = Common.createURL(root, serverURL); List downloaded = null; downloaded = new ArrayList(paths.size()); - if (paths.size() > 500) { + if (paths.size() > downloadParameter && typeOfQuery != MODE_GROUPDAV) { int downloadedCounter = 0; while (downloadedCounter != paths.size()) { int start = downloadedCounter; int finish = 0; - if ((paths.size() - downloadedCounter) > 500) { - finish = (downloadedCounter + 500); + if ((paths.size() - downloadedCounter) > downloadParameter) { + finish = (downloadedCounter + downloadParameter); } else { finish = start + (paths.size() - downloadedCounter); } List toDL = paths.subList((downloadedCounter), finish); - downloaded = _getObjectsInBulk(path, toDL, typeOfQuery, downloaded); + downloaded = performBulkFetch(path, toDL, typeOfQuery, downloadParameter, downloaded); downloadedCounter = (downloadedCounter + toDL.size()); } } else { - downloaded = _getObjectsInBulk(path, paths, typeOfQuery, downloaded); + downloaded = performBulkFetch(path, paths, typeOfQuery, downloadParameter, downloaded); } return downloaded; } - protected List _getObjectsInBulk(URL root, List paths, int typeOfQuery, List addTo) throws Exception { + protected List performBulkFetch( + URL root, + List paths, + int typeOfQuery, + int itemsAtOnce, + List addTo) throws Exception { /* for (String u : paths) { cd.addURLToDownload(u); } return cd.downloadObjects(); */ if (typeOfQuery == MODE_GROUPDAV) { - Stack downloaded = new Stack(); - for (String loc : paths) { - try { - GroupDAVObject obj = this.getObject(loc); - downloaded.add(obj); - } catch (Exception e) { - logger.throwing(this.getClass().getName(), "getObjectsInBulk", e); - } + for (String u: paths) { + cd.addURLToDownload(u); } - return downloaded; - } else if (typeOfQuery == MODE_CALDAV) { + return cd.downloadObjects(addTo,itemsAtOnce); + } else if (typeOfQuery == MODE_CALDAV && paths.size() > 0) { return cdavex.doMultiget(root, paths, addTo); - } else if (typeOfQuery == MODE_CARDDAV) { + } else if (typeOfQuery == MODE_CARDDAV && paths.size() > 0) { return cardex.doMultiget(root, paths, addTo); } return new ArrayList(); @@ -445,17 +438,6 @@ public class groupDAV implements IDAVHandler { } - /** Create a socket to the host */ - private Socket createSocket() throws Exception { - Socket st = null; - if (ssl) { - st = ssf.createSocket(host, po); - } else { - st = new Socket(host, po); - } - return st; - } - private int findContentLength(String data) { String[] headers = data.split("\n"); for (int i = 0; i < headers.length; i++) { @@ -469,68 +451,6 @@ public class groupDAV implements IDAVHandler { return -1; } - /** Sends a request to the server, non-keepalive - * - * @param by A Byte array containing the HTTP request headers and contents - * @return A String of the server result - * @throws java.lang.Exception Due to network error - */ - private String sendNonKeepAliveRequest(byte[] by) throws Exception { - String dbugstring = new String(by); - String loggableString = dbugstring.replace(base64cache, "Authorization: Basic [removed]"); - logger.finer("We sent:\r\n" + loggableString); - // Measure latency - long time = new java.util.Date().getTime(); - Socket st = createSocket(); - st.getOutputStream().write(by); - st.getOutputStream().flush(); - InputStream sc = st.getInputStream(); - BufferedInputStream bis = new BufferedInputStream(sc); - - StringBuffer sb = new StringBuffer(); - int op = 0; - int fouls = 0; - - // We need to process the message character by chacter instead of byte by byte - // or otherwise 2-4 byte characters (many Unicode characters) get stripped away. - // To do this, we use the InputStreamReader class to convert byte stream into - // an Unicode character stream. - BufferedReader charstream = new BufferedReader(new InputStreamReader(bis, "UTF-8")); - - while (op != -1) { - char[] buf = new char[300]; - op = charstream.read(buf); - if (op != 0 && op != -1) { - for (int i = 0; i < op; i++) { - char c = buf[i]; - // Strip bytes which would foul an XML parser, i.e SIF - // for Funambol upstream. See - // http://cse-mjmcl.cse.bris.ac.uk/blog/2007/02/14/1171465494443.html - if ((c == 0x9) || - (c == 0xA) || - (c == 0xD) || - ((c >= 0x20) && (c <= 0xD7FF)) || - ((c >= 0xE000) && (c <= 0xFFFD)) || - ((c >= 0x10000) && (c <= 0x10FFFF))) { - sb.append(c); - } else { - fouls++; - } - } - } - } - - if (fouls > 0) { - logger.fine(fouls + " invalid (XML-wise) characters detected in stream. Is the source/users clean?"); - } - charstream.close(); - bis.close(); - long closetime = new java.util.Date().getTime(); - long rtt = closetime - time; - logger.finer("We got:\r\n" + sb.toString() + "\r\n....in " + rtt + "ms"); - return sb.toString(); - } - /** Returns a list of HTTP/DAV etags. Object URL's are the key in the Map. * If the DAV PROPFIND did not return etag properties in its result * an attempt to get() a etag will return null as per Map implemementation rules diff --git a/src/main/java/net/bionicmessage/objects/MultipleSourceICalendarObjectStore.java b/src/main/java/net/bionicmessage/objects/MultipleSourceICalendarObjectStore.java index 89e3536..38efeaf 100644 --- a/src/main/java/net/bionicmessage/objects/MultipleSourceICalendarObjectStore.java +++ b/src/main/java/net/bionicmessage/objects/MultipleSourceICalendarObjectStore.java @@ -2,7 +2,7 @@ * ICalendarObjectStore.java * * Created on 26 August 2006, 14:56 - * Copyright (c) 2006 Mathew McBride / "BionicMessage.net" + * Copyright (c) 200602008 Mathew McBride / "BionicMessage.net" * * Permission is hereby granted, free of charge, to any person obtaining a * copy of this software and associated documentation files (the "Software"), @@ -31,6 +31,7 @@ import java.io.PrintWriter; import java.io.StringReader; import java.io.StringWriter; import java.sql.SQLException; +import java.sql.Timestamp; import java.util.ArrayList; import java.util.Arrays; import java.util.HashMap; @@ -76,24 +77,8 @@ public class MultipleSourceICalendarObjectStore { public static int OPTION_STOREDPASS = 8; /** Use a single log file */ public static int OPTION_SINGLELOG = 4; - /** Base property for store location */ - public static final String PROPERTY_STORE_LOCATION = "store.location"; - /** Properties name for server */ - public static final String PROPERTY_SERVER = "store.server"; - /** Properties name for user */ - public static final String PROPERTY_USER = "store.user"; - /** Properties name for password */ - public static final String PROPERTY_PASSWORD = "store.password"; - /** Base property for sources */ - public static final String BASE_PROPERTY_SOURCE = "store.source."; - /** CalDAV compare property name */ - public static final String CALDAV_COMPARE_PROPERTY = "store.cdav.property"; - /** CalDAV type property name */ - public static final String CALDAV_COMPARE_COMPONENT = "store.cdav.component"; - /** CalDAV compare start time */ - public static final String CALDAV_COMPARE_START = "store.cdav.start"; - /** CalDAV compare end time */ - public static final String CALDAV_COMPARE_END = "store.cdav.end"; + + boolean sslmode = false; boolean expertmode = false; boolean purgemode = false; @@ -182,9 +167,9 @@ public class MultipleSourceICalendarObjectStore { Iterator listOfProps = props.keySet().iterator(); while (listOfProps.hasNext()) { String key = (String) listOfProps.next(); - if (key.contains(BASE_PROPERTY_SOURCE)) { + if (key.contains(StoreConstants.BASE_PROPERTY_SOURCE)) { String loc = props.getProperty(key); - key = key.replace(BASE_PROPERTY_SOURCE, ""); + key = key.replace(StoreConstants.BASE_PROPERTY_SOURCE, ""); setStore(key, loc); } } @@ -195,8 +180,8 @@ public class MultipleSourceICalendarObjectStore { } public void setServer(String url) { - if (props.getProperty(PROPERTY_SERVER) == null || expertmode) { - props.setProperty(PROPERTY_SERVER, url); + if (props.getProperty(StoreConstants.PROPERTY_SERVER) == null || expertmode) { + props.setProperty(StoreConstants.PROPERTY_SERVER, url); } } @@ -204,24 +189,24 @@ public class MultipleSourceICalendarObjectStore { if (!storeurl.substring(storeurl.length()).equals("/")) { storeurl = storeurl + "/"; } - if (props.getProperty(BASE_PROPERTY_SOURCE + name) == null || expertmode) { - props.setProperty(BASE_PROPERTY_SOURCE + name, storeurl); + if (props.getProperty(StoreConstants.BASE_PROPERTY_SOURCE + name) == null || expertmode) { + props.setProperty(StoreConstants.BASE_PROPERTY_SOURCE + name, storeurl); } sources.put(name, storeurl); } public void connect_Base64(String b64cache) throws Exception { - client = new groupDAV(props.getProperty(PROPERTY_SERVER), b64cache); + client = new groupDAV(props.getProperty(StoreConstants.PROPERTY_SERVER), b64cache); afterConnect(); } public void connect_plain(String user, String pass) throws Exception { - client = new groupDAV(props.getProperty(PROPERTY_SERVER), user, pass); + client = new groupDAV(props.getProperty(StoreConstants.PROPERTY_SERVER), user, pass); afterConnect(); } public void connect_storedpass() throws Exception { - client = new groupDAV(props.getProperty(PROPERTY_SERVER), props.getProperty(PROPERTY_USER), props.getProperty(PROPERTY_PASSWORD)); + client = new groupDAV(props.getProperty(StoreConstants.PROPERTY_SERVER), props.getProperty(StoreConstants.PROPERTY_USER), props.getProperty(StoreConstants.PROPERTY_PASSWORD)); afterConnect(); } @@ -259,24 +244,26 @@ public class MultipleSourceICalendarObjectStore { Summary summ = (Summary) vcal.getProperty("SUMMARY"); long dtstart = 0; long dtend = 0; + Timestamp ds = null; + Timestamp de = null; if (vcal.getName().equals(VEvent.VEVENT)) { DtStart dts = (DtStart) vcal.getProperty("DTSTART"); DtEnd dte = (DtEnd) vcal.getProperty("DTEND"); - java.util.Date dts_date = (java.util.Date) dts.getDate(); - java.util.Date dte_date = null; - if (dte == null) { // all day event - // TODO: handle as dts_date+24h or dts_date? - dte_date = dts_date; - } else { - dte_date = dte.getDate(); - } - dtstart = dts_date.getTime() / 1000; - dtend = dte_date.getTime() / 1000; - dts = null; - dte = null; - ; + ds = new Timestamp(dts.getDate().getTime()); + de = new Timestamp(dte.getDate().getTime()); + } else { + // VTODO: + ds = new Timestamp(0); // just fill with empty (current time) + de = new Timestamp(0); } - obtrack.createObject(storeName, uid.getValue(), obj.getLocation(), obj.getEtag(), summ.getValue().trim(), obj.getContent(), dtstart, dtend); + obtrack.createObject(storeName, + uid.getValue(), + obj.getLocation(), + obj.getEtag(), + summ.getValue().trim(), + obj.getContent(), + ds, + de); logList.add(uid.getValue()); return uid.getValue(); } @@ -286,15 +273,14 @@ public class MultipleSourceICalendarObjectStore { Calendar cd = constructCalendarObject(obj.getContent()); Component vcal = (Component) cd.getComponents().get(0); Summary summ = (Summary) vcal.getProperty("SUMMARY"); - long dtstart = 0; - long dtend = 0; + Timestamp dtstart = null; + Timestamp dtend = null; if (vcal.getName().equals(VEvent.VEVENT)) { DtStart dts = (DtStart) vcal.getProperty("DTSTART"); DtEnd dte = (DtEnd) vcal.getProperty("DTEND"); - dtstart = dts.getDate().getTime(); - dtend = dts.getDate().getTime(); - dts = null; - dte = null; + dtstart = new Timestamp(dts.getDate().getTime()); + dtend = new Timestamp(dte.getDate().getTime()); + } obtrack.updateEtag(uid, obj.getEtag()); obtrack.updateObject(uid, cd.toString()); @@ -347,6 +333,8 @@ public class MultipleSourceICalendarObjectStore { public int replaceObject(String storeName, String uid, String name, String contents, long dtstart, long dtend) throws Exception { String oldetag = obtrack.getObjectEtag(uid); GroupDAVObject gbo = client.modifyObject(obtrack.getObjectURL(uid), contents, oldetag); + if (gbo == null) + return 403; obtrack.deleteObject(uid); addFromServerToStore(storeName, gbo.getLocation(), updatedOnServer); return 0; @@ -355,16 +343,10 @@ public class MultipleSourceICalendarObjectStore { public String searchUids(String name, long dstime, long detime) throws Exception { // Find potential names @SuppressWarnings("unchecked") - ArrayList potentialNames = obtrack.findObjectsByName(name); - for (int i = 0; i < potentialNames.size(); i++) { - String id = potentialNames.get(i); - // Do we have a match? - boolean match = obtrack.doesUidMatchTimes(id, dstime, detime); - if (match) { - return id; - } - } - return null; + Timestamp ds = new Timestamp(dstime*1000); + Timestamp de = new Timestamp(detime*1000); + String match = obtrack.findObjectByDtStartDtEnd(ds, de); + return match; } public void deleteObject(String uid) throws Exception { @@ -426,12 +408,12 @@ public class MultipleSourceICalendarObjectStore { while (sourceList.hasNext()) { String sourceName = sourceList.next(); String sourceLoc = sources.get(sourceName); - serverMode = client.getUseMode(sourceLoc); - // Are we using GroupDAV or CalDAV propfind? + serverMode = this.getCollectionType(sourceLoc); + int downloaderParameter = this.getDownloaderParameter(serverMode); List objectsForSource = null; List toDownload = null; Map etags = null; - if (props.getProperty(CALDAV_COMPARE_COMPONENT) == null) { + if (props.getProperty(StoreConstants.CALDAV_COMPARE_COMPONENT) == null) { objectsForSource = client.listObjects(sourceLoc); etags = client.getEtags(); } else { @@ -446,6 +428,7 @@ public class MultipleSourceICalendarObjectStore { toDownload = new ArrayList(objectsForSource.size()); for (int i = 0; i < objectsForSource.size(); i++) { String url = (String) objectsForSource.get(i); + try { // Do we have the object? String stuid = urluid.get(url); if (stuid != null) { @@ -458,28 +441,31 @@ public class MultipleSourceICalendarObjectStore { } log.fine("We have the URL: " + url); } else { - try { - toDownload.add(url); - //addFromServerToStore(sourceName, url); - log.fine("We added the URL: " + url); - } catch (Exception ex) { - log.throwing(this.getClass().getName(), "startSync", ex); - ex.printStackTrace(); - } + toDownload.add(url); // No we don't have the URL, add to queue + } + } catch (Exception ex) { + log.throwing(this.getClass().getName(), "URL: " + url, ex); + ex.printStackTrace(); } } } else if (purgemode) { toDownload = objectsForSource; } - List bulkToAdd = client.getObjectsInBulk(sourceLoc, toDownload, serverMode); - for (GroupDAVObject groupDAVObject : bulkToAdd) { - try { - addFromServerToStore(sourceLoc, groupDAVObject, addedToStore); - } catch (Exception ex) { - log.throwing(this.getClass().getName(), "startSync", ex); - ex.printStackTrace(); + if (toDownload.size() > 0) { + log.info(toDownload.size() + " objects to get. Doing bulk"); + List bulkToAdd = client.getObjectsInBulk(sourceLoc, toDownload, serverMode, downloaderParameter); + for (GroupDAVObject groupDAVObject : bulkToAdd) { + try { + addFromServerToStore(sourceLoc, groupDAVObject, addedToStore); + log.fine("We added the URL: " + groupDAVObject.getLocation()); + } catch (Exception ex) { + log.throwing(this.getClass().getName(), "startSync", ex); + ex.printStackTrace(); + } } + log.info("Done processing.."); } + ArrayList URLarray = obtrack.getURLListForSource(sourceName); for (int i = 0; i < URLarray.size(); i++) { String url = (String) URLarray.get(i); @@ -489,6 +475,7 @@ public class MultipleSourceICalendarObjectStore { } } } + log.info("Sync finished"); } /** Returns a list of UIDs that have not been modified in the last @@ -555,7 +542,7 @@ public class MultipleSourceICalendarObjectStore { /** Test method */ public List _listURLsByTimeRange(String source, String type, DateProperty start, DateProperty end) throws Exception { - String actualpath = props.getProperty(BASE_PROPERTY_SOURCE + source); + String actualpath = props.getProperty(StoreConstants.BASE_PROPERTY_SOURCE + source); Map urlsInTime = client.getURLsByEventEnding(actualpath, start.getValue(), end.getValue()); String[] urls = new String[urlsInTime.size()]; @@ -565,10 +552,10 @@ public class MultipleSourceICalendarObjectStore { /** Get a map of URL's and Etag's by specified time range */ public Map cDAVGetURLsEtagsByTimeRange(String path) throws Exception { - String componentType = props.getProperty(CALDAV_COMPARE_COMPONENT); - String comparator = props.getProperty(CALDAV_COMPARE_PROPERTY); - String start = props.getProperty(CALDAV_COMPARE_START); - String end = props.getProperty(CALDAV_COMPARE_END); + String componentType = props.getProperty(StoreConstants.CALDAV_COMPARE_COMPONENT); + String comparator = props.getProperty(StoreConstants.CALDAV_COMPARE_PROPERTY); + String start = props.getProperty(StoreConstants.CALDAV_COMPARE_START); + String end = props.getProperty(StoreConstants.CALDAV_COMPARE_END); if (componentType != null) { return client.getURLsByTimeRange(path, componentType, comparator, start, end); } @@ -585,11 +572,12 @@ public class MultipleSourceICalendarObjectStore { if (url == null) { throw new Exception("URL for " + uid + " is null"); } + try { String etag = obtrack.getObjectEtag(uid); String name = obtrack.getObjectName(uid); String data = obtrack.getObjectContents(uid); - long dtstart = 0; - long dtend = 0; + Timestamp dtstart = null; + Timestamp dtend = null; dtstart = obtrack.getDtStartForUid(uid); dtend = obtrack.getDtEndFromUid(uid); lw.println("----------"); @@ -597,11 +585,15 @@ public class MultipleSourceICalendarObjectStore { lw.println("URL:" + url); lw.println("ETAG:" + etag); lw.println("NAME:" + name); - lw.println("DTSTART:" + dtstart); - lw.println("DTEND:" + dtend); + lw.println("DTSTART:" + dtstart.toString()); + lw.println("DTEND:" + dtend.toString()); lw.println("DATA FOLLOWS:"); lw.println(data); lw.println("----------"); + } catch (Exception e) { + System.err.println("Error trying to get: "+uid); + e.printStackTrace(); + } } lw.println("Objects added to store: "); for (int i = 0; i < addedToStore.size(); i++) { @@ -676,4 +668,24 @@ public class MultipleSourceICalendarObjectStore { ex.printStackTrace(); } } + + private int getCollectionType(String path) throws Exception { + String srvMode = props.getProperty(StoreConstants.PROPERTY_SERVER_MODE); + if (srvMode == null) + return client.getUseMode(path); + else if (srvMode.equals("caldav")) + return 1; + else if (srvMode.equals("carddav")) + return 2; + return 0; + } + private int getDownloaderParameter(int type) { + if (type == 2) { + String itemsAtOnce = props.getProperty(StoreConstants.PROPERTY_SERVER_ITEMS); + return Integer.parseInt(itemsAtOnce); + } else { + String cthreads = props.getProperty(StoreConstants.PROPERTY_SERVER_CTHREADS); + return Integer.parseInt(cthreads); + } + } } diff --git a/src/main/java/net/bionicmessage/objects/MultipleSourceObjectTracking.java b/src/main/java/net/bionicmessage/objects/MultipleSourceObjectTracking.java index 42145fe..e4593d7 100644 --- a/src/main/java/net/bionicmessage/objects/MultipleSourceObjectTracking.java +++ b/src/main/java/net/bionicmessage/objects/MultipleSourceObjectTracking.java @@ -158,8 +158,8 @@ public class MultipleSourceObjectTracking { String etag, String name, String contents, - long dtstart, - long dtend) throws SQLException { + Timestamp dtstart, + Timestamp dtend) throws SQLException { String newuid = String.format("INSERT INTO %s (\"OBJ_SOURCE\", \"OBJ_UID\") VALUES ('%s','%s')", OBJLIST, sourceName, uid); executeSQL(newuid); @@ -176,8 +176,14 @@ public class MultipleSourceObjectTracking { innewobject.setString(1, uid); innewobject.setBytes(2, contents.getBytes()); innewobject.execute(); - String insertdates = "INSERT INTO " + DATELIST + "(\"OBJ_UID\",\"OBJ_DTSTART\",\"OBJ_DTEND\") VALUES ('" + uid + "','" + dtstart + "','" + dtend + "')"; - executeSQL(insertdates); + if (dtstart == null && dtend == null) + return; + String insertdates = "INSERT INTO " + DATELIST + "(\"OBJ_UID\",\"OBJ_DTSTART\",\"OBJ_DTEND\") VALUES (?,?,?)"; + PreparedStatement innewdates = conn.prepareStatement(insertdates); + innewdates.setString(1, uid); + innewdates.setTimestamp(2, dtstart); + innewdates.setTimestamp(3, dtend); + innewdates.execute(); } public void deleteObject(String uid) throws SQLException { @@ -195,15 +201,6 @@ public class MultipleSourceObjectTracking { executeSQL(deletedate); } - public boolean doesUidMatchTimes(String uid, long dstime, long detime) throws SQLException { - String findDate = String.format("SELECT \"OBJ_UID\" FROM \"%s\" WHERE \"OBJ_UID\" = '%s' AND \"OBJ_DTSTART\" = %d AND \"OBJ_DTEND\" = %d", DATELIST, uid, dstime, detime); - String result = get1x1SQL(findDate); - if (result != null) { - return true; - } - return false; - } - public String findObjectByURL(String url) throws SQLException { cachedURLSUIDs = getURLUIDcache(); return cachedURLSUIDs.get(url); @@ -215,7 +212,24 @@ public class MultipleSourceObjectTracking { String result = get1x1SQL(findUid); return result; } - + /** Searches for objects with a matching dtstart and dtend. + * + * @param dtstart DateStart + * @param dtend DateEnd + * @return The UID of the object matching the criteria, or null if no result + * @throws java.sql.SQLException due to database error + */ + public String findObjectByDtStartDtEnd(Timestamp dtstart, Timestamp dtend) throws SQLException { + String query = "select DATELIST.OBJ_UID from DATELIST JOIN namelist WHERE DATELIST.OBJ_DTSTART = ? AND DATELIST.OBJ_DTEND = ?"; + PreparedStatement stmt = conn.prepareStatement(query); + stmt.setTimestamp(1, dtstart); + stmt.setTimestamp(2, dtend); + ResultSet rs = stmt.executeQuery(); /* todo, place next three lines into a func */ + rs.next(); + if (rs.getRow() == 0) + return null; + return rs.getString(1); + } public ArrayList findObjectsByName(String name) throws SQLException { ArrayList results = new ArrayList(); name = name.replace("'", "\""); @@ -288,7 +302,6 @@ public class MultipleSourceObjectTracking { public void updateObject(String uid, String content) throws SQLException { String deleteobject = "DELETE FROM " + OBJECTS + " WHERE \"OBJ_UID\" = '" + uid + "'"; executeSQL(deleteobject); - String objectBase64 = Base64.encodeBytes(content.getBytes()); String newobject = "INSERT INTO " + OBJECTS + "(\"OBJ_UID\",\"OBJ_CONTENTS\") VALUES (?,?)"; PreparedStatement innewobject = conn.prepareStatement(newobject); innewobject.setString(1, uid); @@ -296,11 +309,13 @@ public class MultipleSourceObjectTracking { boolean executed = innewobject.execute(); } - public void updateDate(String uid, long dtstart, long dtend) throws SQLException { - String deletedate = "DELETE FROM " + DATELIST + " WHERE \"OBJ_UID\" = '" + uid + "'"; - executeSQL(deletedate); - String newdate = "INSERT INTO " + DATELIST + "(\"OBJ_UID\",\"OBJ_DTSTART\",\"OBJ_DTEND\") VALUES ('" + uid + "'," + dtstart + "," + dtend + ")"; - executeSQL(newdate); + public void updateDate(String uid, Timestamp dtstart, Timestamp dtend) throws SQLException { + String stmt = "UPDATE " + DATELIST + " SET OBJ_DTSTART=?, OBJ_DTEND=? WHERE OBJ_UID=?"; + PreparedStatement updateDate = conn.prepareStatement(stmt); + updateDate.setTimestamp(1, dtstart); + updateDate.setTimestamp(2, dtend); + updateDate.setString(3, uid); + updateDate.execute(); } public boolean doesObjectExist(String uid) throws SQLException { @@ -345,30 +360,31 @@ public class MultipleSourceObjectTracking { } return uidetag; } - public boolean doesObjectApplyAtTime(String uid, int time) throws SQLException { - String findObject = "SELECT \"OBJ_UID\" FROM \"" + DATELIST + "\" WHERE \"OBJ_UID\" = '" + uid + "' AND WHERE \"OBJ_DTSTART\" <= " + time + " AND \"OBJ_DTEND\" >= " + time; - Statement stmt = conn.createStatement(); - stmt.execute(findObject); - ResultSet rs = stmt.getResultSet(); + public boolean doesObjectApplyAtTime(String uid, java.sql.Timestamp time) throws SQLException { + String findObject = "SELECT \"OBJ_UID\" FROM \"" + DATELIST + "\" WHERE \"OBJ_UID\" = '" + uid + "' AND WHERE \"OBJ_DTSTART\" <= ? AND \"OBJ_DTEND\" >= ?"; + PreparedStatement stmt = conn.prepareStatement(findObject); + stmt.setTimestamp(1, time); + stmt.setTimestamp(2, time); + ResultSet rs = stmt.executeQuery(); return rs.next(); } - public long getDtStartForUid(String uid) throws SQLException { + public Timestamp getDtStartForUid(String uid) throws SQLException { String findUid = "SELECT \"OBJ_DTSTART\" FROM \"" + DATELIST + "\" WHERE \"OBJ_UID\" = '" + uid + "'"; Statement stmt = conn.createStatement(); stmt.execute(findUid); ResultSet rs = stmt.getResultSet(); rs.next(); - return rs.getLong("OBJ_DTSTART"); + return rs.getTimestamp("OBJ_DTSTART"); } - public long getDtEndFromUid(String uid) throws SQLException { + public Timestamp getDtEndFromUid(String uid) throws SQLException { String findUid = "SELECT \"OBJ_DTEND\" FROM \"" + DATELIST + "\" WHERE \"OBJ_UID\" = '" + uid + "'"; Statement stmt = conn.createStatement(); stmt.execute(findUid); ResultSet rs = stmt.getResultSet(); rs.next(); - return rs.getLong("OBJ_DTEND"); + return rs.getTimestamp("OBJ_DTEND"); } public ArrayList getUIDList() throws SQLException { @@ -508,8 +524,8 @@ public class MultipleSourceObjectTracking { public static final String CREATE_DATELIST = "CREATE TABLE datelist(\n" + "OBJ_UID VARCHAR(255) not null," + - "OBJ_DTSTART INT not null," + - "OBJ_DTEND INT not null" + + "OBJ_DTSTART TIMESTAMP not null," + + "OBJ_DTEND TIMESTAMP not null" + ")"; public static final String CREATE_NOTWANTED = "CREATE TABLE notwanted(\n" + diff --git a/src/main/java/net/bionicmessage/objects/MultipleSourceVCardObjectStore.java b/src/main/java/net/bionicmessage/objects/MultipleSourceVCardObjectStore.java index 711af6a..058d011 100644 --- a/src/main/java/net/bionicmessage/objects/MultipleSourceVCardObjectStore.java +++ b/src/main/java/net/bionicmessage/objects/MultipleSourceVCardObjectStore.java @@ -252,7 +252,7 @@ public class MultipleSourceVCardObjectStore { n = name.toString(); } obtrack.createObject(storeName, uid, obj.getLocation(), obj.getEtag(), - n.trim(), obj.getContent(), 0, 0); + n.trim(), obj.getContent(), null,null); toAdd.add(uid); return uid; } @@ -330,6 +330,8 @@ public class MultipleSourceVCardObjectStore { String contents) throws Exception { String oldetag = obtrack.getObjectEtag(uid); GroupDAVObject gbo = client.modifyObject(obtrack.getObjectURL(uid), contents, oldetag); + if (gbo == null) + return 403; updatedOnServer.add(uid); obtrack.updateObject(uid, contents); obtrack.updateEtag(uid, gbo.getEtag()); @@ -394,28 +396,12 @@ public class MultipleSourceVCardObjectStore { while (sourceList.hasNext()) { String sourceName = sourceList.next(); String sourceLoc = sources.get(sourceName); - int useMode = client.getUseMode(sourceLoc); + int useMode = this.getCollectionType(sourceLoc); + int downloaderParameter = this.getDownloaderParameter(useMode); List objectsForSource = client.listObjects(sourceLoc); - /* if (purgemode) { // When we have nothing and want it all - - List everything = - client.getAllObjectsInPath(sourceLoc, useMode); - for (GroupDAVObject obj : everything) { - try { - addFromServerToStore(sourceName, obj, addedToStore); - log.fine("We added the URL: " + obj.getLocation()); - } catch (Exception e) { - log.throwing(this.getClass().getName(), "startSync", e); - log.info("Error parsing from: " + obj.getLocation()); - } - } - } else { */ List objects = client.listObjects(sourceLoc); Map etags = client.getEtags(); List toDownload = new ArrayList(objects.size()); - // Make a stack - // Pop it until empty - // Fetch two at once. Map localCache = obtrack.getURLUIDcache(); Map setagCache = obtrack.getUidEtagCache(); for (int i = 0; i < objects.size(); i++) { @@ -438,7 +424,7 @@ public class MultipleSourceVCardObjectStore { } } if (toDownload.size() > 0) { - List downloadedObjs = client.getObjectsInBulk(sourceLoc, toDownload, useMode); + List downloadedObjs = client.getObjectsInBulk(sourceLoc, toDownload, useMode,downloaderParameter); for (GroupDAVObject obj : downloadedObjs) { try { addFromServerToStore(sourceName, obj, addedToStore); @@ -566,14 +552,8 @@ public class MultipleSourceVCardObjectStore { public String searchUids(String name) throws Exception { // Find potential names ArrayList potentialNames = obtrack.findObjectsByName(name); - for (int i = 0; i < potentialNames.size(); i++) { - String id = potentialNames.get(i); - // Do we have a match? - boolean match = obtrack.doesUidMatchTimes(id, 0, 0); - if (match) { - return id; - } - } + if (potentialNames.size() > 0) + return potentialNames.get(0); return null; } @@ -615,4 +595,27 @@ public class MultipleSourceVCardObjectStore { ex.printStackTrace(); } } + /** + * Return the collection type for the specified path + * @param path + * @return + * @throws java.lang.Exception Due to network error. + */ + private int getCollectionType(String path) throws Exception { + String srvMode = props.getProperty(StoreConstants.PROPERTY_SERVER_MODE); + if (srvMode == null) + return client.getUseMode(path); + else if (srvMode.equals("carddav")) + return 2; + return 0; + } + private int getDownloaderParameter(int type) { + if (type == 2) { + String itemsAtOnce = props.getProperty(StoreConstants.PROPERTY_SERVER_ITEMS); + return Integer.parseInt(itemsAtOnce); + } else { + String cthreads = props.getProperty(StoreConstants.PROPERTY_SERVER_CTHREADS); + return Integer.parseInt(cthreads); + } + } } diff --git a/src/test/java/CalDAVExtensions.java b/src/test/java/CalDAVExtensions.java index ace7741..840bfee 100644 --- a/src/test/java/CalDAVExtensions.java +++ b/src/test/java/CalDAVExtensions.java @@ -12,6 +12,7 @@ import java.util.Iterator; import java.util.List; import java.util.Properties; import net.bionicmessage.objects.MultipleSourceICalendarObjectStore; +import net.bionicmessage.objects.StoreConstants; import net.fortuna.ical4j.data.CalendarBuilder; import net.fortuna.ical4j.model.Calendar; import net.fortuna.ical4j.model.ComponentList; @@ -162,10 +163,10 @@ public class CalDAVExtensions { obtrack = new MultipleSourceICalendarObjectStore(testProperties.getProperty("store.location"), MultipleSourceICalendarObjectStore.OPTION_PURGE); - testProperties.setProperty(MultipleSourceICalendarObjectStore.CALDAV_COMPARE_COMPONENT, "VEVENT"); - testProperties.setProperty(MultipleSourceICalendarObjectStore.CALDAV_COMPARE_PROPERTY, "DTSTART"); - testProperties.setProperty(MultipleSourceICalendarObjectStore.CALDAV_COMPARE_START, "20080514T120000Z"); - testProperties.setProperty(MultipleSourceICalendarObjectStore.CALDAV_COMPARE_END, "20080525T120000Z"); + testProperties.setProperty(StoreConstants.CALDAV_COMPARE_COMPONENT, "VEVENT"); + testProperties.setProperty(StoreConstants.CALDAV_COMPARE_PROPERTY, "DTSTART"); + testProperties.setProperty(StoreConstants.CALDAV_COMPARE_START, "20080514T120000Z"); + testProperties.setProperty(StoreConstants.CALDAV_COMPARE_END, "20080525T120000Z"); obtrack.setProperties(testProperties); obtrack.loadSourcesFromProps(); obtrack.connect_storedpass(); @@ -183,17 +184,17 @@ public class CalDAVExtensions { } } obtrack.close(); - testProperties.remove(MultipleSourceICalendarObjectStore.CALDAV_COMPARE_COMPONENT); - testProperties.remove(MultipleSourceICalendarObjectStore.CALDAV_COMPARE_PROPERTY); - testProperties.remove(MultipleSourceICalendarObjectStore.CALDAV_COMPARE_START); - testProperties.remove(MultipleSourceICalendarObjectStore.CALDAV_COMPARE_END); + testProperties.remove(StoreConstants.CALDAV_COMPARE_COMPONENT); + testProperties.remove(StoreConstants.CALDAV_COMPARE_PROPERTY); + testProperties.remove(StoreConstants.CALDAV_COMPARE_START); + testProperties.remove(StoreConstants.CALDAV_COMPARE_END); obtrack = new MultipleSourceICalendarObjectStore(testProperties.getProperty("store.location"), MultipleSourceICalendarObjectStore.OPTION_PURGE); - testProperties.setProperty(MultipleSourceICalendarObjectStore.CALDAV_COMPARE_COMPONENT, "VEVENT"); - testProperties.setProperty(MultipleSourceICalendarObjectStore.CALDAV_COMPARE_PROPERTY, "DTSTART"); - testProperties.setProperty(MultipleSourceICalendarObjectStore.CALDAV_COMPARE_START, "20080514T120000Z"); - testProperties.setProperty(MultipleSourceICalendarObjectStore.CALDAV_COMPARE_END, "20080525T120000Z"); + testProperties.setProperty(StoreConstants.CALDAV_COMPARE_COMPONENT, "VEVENT"); + testProperties.setProperty(StoreConstants.CALDAV_COMPARE_PROPERTY, "DTSTART"); + testProperties.setProperty(StoreConstants.CALDAV_COMPARE_START, "20080514T120000Z"); + testProperties.setProperty(StoreConstants.CALDAV_COMPARE_END, "20080525T120000Z"); obtrack.setProperties(testProperties); obtrack.loadSourcesFromProps(); obtrack.connect_storedpass(); diff --git a/src/test/java/MultipleSourceICalendarObjectStoreTest.java b/src/test/java/MultipleSourceICalendarObjectStoreTest.java index 44f6b91..8ffaa1e 100644 --- a/src/test/java/MultipleSourceICalendarObjectStoreTest.java +++ b/src/test/java/MultipleSourceICalendarObjectStoreTest.java @@ -62,7 +62,7 @@ public class MultipleSourceICalendarObjectStoreTest { } testProps = new Properties(); testProps.load(new FileInputStream(testFile)); - String storePath = testProps.getProperty(MultipleSourceICalendarObjectStore.PROPERTY_STORE_LOCATION); + String storePath = testProps.getProperty(StoreConstants.PROPERTY_STORE_LOCATION); stPath = new File(storePath); boolean create = stPath.mkdirs(); int options = 0; diff --git a/src/test/java/MultipleSourceICalendarObjectStoreTodoTest.java b/src/test/java/MultipleSourceICalendarObjectStoreTodoTest.java index 75bbc58..3033ae5 100644 --- a/src/test/java/MultipleSourceICalendarObjectStoreTodoTest.java +++ b/src/test/java/MultipleSourceICalendarObjectStoreTodoTest.java @@ -56,7 +56,7 @@ public class MultipleSourceICalendarObjectStoreTodoTest { } testProps = new Properties(); testProps.load(new FileInputStream(testFile)); - String storePath = testProps.getProperty(MultipleSourceICalendarObjectStore.PROPERTY_STORE_LOCATION); + String storePath = testProps.getProperty(StoreConstants.PROPERTY_STORE_LOCATION); stPath = new File(storePath); boolean create = stPath.mkdirs(); int options = MultipleSourceICalendarObjectStore.OPTION_TODO; diff --git a/src/test/java/groupdavTest.java b/src/test/java/groupdavTest.java index c1a2799..9ba755c 100644 --- a/src/test/java/groupdavTest.java +++ b/src/test/java/groupdavTest.java @@ -49,6 +49,13 @@ public class groupdavTest { GroupDAVObject index = gdav.getObject("http://comalies.citadel.org/"); } @Test + public void testSetupAndHTTPSGet() throws Exception { + groupDAV gdav = new groupDAV("https://www.godaddy.com", + "test", + "test"); + GroupDAVObject index = gdav.getObject("http://www.godaddy.com/"); + } + @Test public void testBuildPropFind() throws Exception { groupDAV gdav = new groupDAV("http://comalies.citadel.org", "test", -- 2.11.4.GIT