diff --git a/ical4j-connector-dav/src/main/java/org/ical4j/connector/dav/PathResolver.java b/ical4j-connector-dav/src/main/java/org/ical4j/connector/dav/PathResolver.java index c5c3a15..7d93027 100644 --- a/ical4j-connector-dav/src/main/java/org/ical4j/connector/dav/PathResolver.java +++ b/ical4j-connector-dav/src/main/java/org/ical4j/connector/dav/PathResolver.java @@ -57,58 +57,81 @@ public interface PathResolver { * @param resourcePath a path component representing a resource * @return a string representing the repository path to the resource */ - String getRepositoryPath(String resourcePath, String wspPath); + String getCalendarPath(String resourcePath, String wspPath); + + String getCardPath(String resourcePath, String wspPath); String getResourceName(String repositoryPath, String wspPath); + /** + * Default path resolver configurations for some popular CalDAV/CardDAV implementations. + * + * Each configuration provides a pattern for the follow path types: + * - principals, or who has access to the calendar/card resources + * - calendar collections, containers for icalendar objects + * - card collections, containers for vcard objects + * + * A configuration also provides a general path pattern that is used to extract the component paths + * from a full repository path, such that: + * - pathPattern(principalPath(resource))[resource] == resource + * - pathPattern(calendarPath(resource))[resource] == resource + * - pathPattern(cardPath(resource))[resource] == resource + */ enum Defaults implements PathResolver { - CHANDLER( "/%s/", "/users/%s", - "/users/(\\w+)/?"), + CHANDLER( "/%s/", "/users/%s", "", + "/users/(?\\w+)/?"), - RADICALE( "/%s", "/", "/([\\w]+)/?"), + RADICALE( "/%s", + "/%2$s/%1$s", + "/%2$s/%1$s", + "\\/(?[\\w]+)\\/(?[\\w]+)"), - BAIKAL( "/", "/calendars/%s", - "/calendars/([\\w]+)/?"), + BAIKAL( "/principals/%s", + "/calendars/%2$s/%1$s", + "/addressbooks/%2$s/%1$s", + "\\/(?(principals|calendars|addressbooks))\\/((?[\\w]+)\\/)?(?[\\w]+)"), - CGP("/", "/", "/(\\w+)/?"), + CGP("/", "/", "","/(?\\w+)/?"), - KMS("/", "/", "/(\\w+)/?"), + KMS("/", "/", "","/(?\\w+)/?"), - ZIMBRA("/principals/users/%s/", "/dav/%s/", - "/(\\w+)/?"), + ZIMBRA("/principals/users/%s/", "/dav/%s/", "", + "/(?\\w+)/?"), - ICAL_SERVER( "/principals/users/%s/", "/dav/%s/", - "/(\\w+)/?"), + ICAL_SERVER( "/principals/users/%s/", "/dav/%s/", "", + "/(?\\w+)/?"), - CALENDAR_SERVER( "/%s/", "/%s", "/(\\w+)/?"), + CALENDAR_SERVER( "/%s/", "/dav/%s", "","/(?\\w+)/?"), - GCAL( "/%s/user", "/%s/events", - "/\\w+/events/?"), + GCAL( "/%s/user", "/%s/events", "", + "/(?\\w+)/events/?"), - SOGO("/%s/", "/%s/", "/(\\w+)/?"), + SOGO("/%s/", "/%s/", "","/(?\\w+)/?"), - DAVICAL("/%s/", "/%s/", "/(\\w+)/?"), + DAVICAL("/%s/", "/%s/", "","/(?\\w+)/?"), - BEDEWORK("/principals/users/%s/", "/users/%s", - "/users/(\\w+)/?"), + BEDEWORK("/principals/users/%s/", "/ucaldav/users/%s", "", + "/users/(?\\w+)/?"), - ORACLE_CS("/principals/%s/", "/home/%s/", - "/home/(\\w+)/?"), + ORACLE_CS("/principals/%s/", "/home/%s/", "", + "/home/(?\\w+)/?"), - GENERIC("/%s", "/%s", "/(\\w+)"); + GENERIC("/%s", "/%s", "","/(?\\w+)"); - private final String principalPathBase; + private final String principalPath; - private final String calendarPathBase; + private final String calendarPath; - private final Pattern calendarPathPattern; + private final String cardPath; - Defaults(String principalPathBase, String calendarPathBase, - String calendarPathPattern) { - this.principalPathBase = principalPathBase; - this.calendarPathBase = calendarPathBase; - this.calendarPathPattern = Pattern.compile("^" + calendarPathPattern + "$"); + private final Pattern pathPattern; + + Defaults(String principalPath, String calendarPath, String cardPath, String pathPattern) { + this.principalPath = principalPath; + this.calendarPath = calendarPath; + this.cardPath = cardPath; + this.pathPattern = Pattern.compile(pathPattern); } /** @@ -118,12 +141,23 @@ enum Defaults implements PathResolver { * @return the user path for a server implementation */ @Override - public String getRepositoryPath(String resourceName, String wspPath) { + public String getCalendarPath(String resourceName, String wspPath) { + if (wspPath != null && !wspPath.isEmpty()) { + return String.format("/%s", String.format(calendarPath, resourceName, wspPath)) + .replaceAll("/+", "/"); + } else { + return String.format("/%s", String.format(calendarPath, resourceName, "")) + .replaceAll("/+", "/"); + } + } + + @Override + public String getCardPath(String resourcePath, String wspPath) { if (wspPath != null && !wspPath.isEmpty()) { - return String.format("/%s%s", wspPath, String.format(calendarPathBase, resourceName)) + return String.format("/%s", String.format(cardPath, resourcePath, wspPath)) .replaceAll("/+", "/"); } else { - return String.format("/%s", String.format(calendarPathBase, resourceName)) + return String.format("/%s", String.format(cardPath, resourcePath, "")) .replaceAll("/+", "/"); } } @@ -135,13 +169,16 @@ public String getRepositoryPath(String resourceName, String wspPath) { */ @Override public String getResourceName(String repositoryPath, String wspPath) { - Matcher matcher = calendarPathPattern.matcher(repositoryPath); - if (matcher.matches() && matcher.groupCount() > 0) { - if (wspPath != null && !wspPath.isEmpty()) { - return String.format("%s/%s", wspPath, matcher.group(1)); - } else { - return matcher.group(1); - } + Matcher matcher = pathPattern.matcher(repositoryPath); +// if (matcher.matches() && matcher.groupCount() > 0) { +// if (wspPath != null && !wspPath.isEmpty()) { +// return String.format("%s/%s", wspPath, matcher.group(1)); +// } else { +// return matcher.group(1); +// } +// } + if (matcher.matches()) { + return matcher.group("resource"); } return null; } @@ -154,7 +191,7 @@ public String getResourceName(String repositoryPath, String wspPath) { */ @Override public String getPrincipalPath(String calendarId) { - return String.format(principalPathBase, calendarId); + return String.format(principalPath, calendarId); } } }