From 12962b58b37fbfda8ddcfe89d78613cc7a58dfdc Mon Sep 17 00:00:00 2001 From: srosse <none@none> Date: Mon, 14 Mar 2016 12:06:10 +0100 Subject: [PATCH] OO-1934: enhance all calendars for Outlook compatibility, add TTL property --- .../olat/commons/calendar/ICalServlet.java | 89 ++++++++++++++++++- .../manager/ICalFileCalendarManager.java | 7 +- 2 files changed, 89 insertions(+), 7 deletions(-) diff --git a/src/main/java/org/olat/commons/calendar/ICalServlet.java b/src/main/java/org/olat/commons/calendar/ICalServlet.java index 77e2a552c48..42879439b15 100644 --- a/src/main/java/org/olat/commons/calendar/ICalServlet.java +++ b/src/main/java/org/olat/commons/calendar/ICalServlet.java @@ -56,12 +56,12 @@ import org.olat.core.util.StringHelper; import org.olat.core.util.i18n.I18nManager; import net.fortuna.ical4j.data.CalendarBuilder; -import net.fortuna.ical4j.data.CalendarOutputter; import net.fortuna.ical4j.data.ParserException; import net.fortuna.ical4j.model.Calendar; import net.fortuna.ical4j.model.Component; import net.fortuna.ical4j.model.ComponentList; import net.fortuna.ical4j.model.Parameter; +import net.fortuna.ical4j.model.Property; import net.fortuna.ical4j.model.PropertyList; import net.fortuna.ical4j.model.ValidationException; import net.fortuna.ical4j.model.component.VEvent; @@ -83,13 +83,15 @@ import net.fortuna.ical4j.util.Strings; * Initial Date: June 1, 2008 * * @author Udit Sajjanhar + * @author srosse, stephane.rosse@frentix.com, http://www.frentix.com */ public class ICalServlet extends HttpServlet { private static final long serialVersionUID = -155266285395912535L; private static final OLog log = Tracing.createLoggerFor(ICalServlet.class); - private final int cacheAge = 60 * 60 * 12; + private static final int TTL_HOURS = 6; + private static final int cacheAge = 60 * 60 * TTL_HOURS;//6 Hours private static final ConcurrentMap<String,VTimeZone> outlookVTimeZones = new ConcurrentHashMap<>(); /** collection of iCal feed prefixs **/ @@ -226,9 +228,8 @@ public class ICalServlet extends HttpServlet { } else { // read and return the calendar file Calendar calendar = calendarManager.readCalendar(calendarType, calendarID); - updateUrlProperties(calendar); DBFactory.getInstance().commitAndCloseSession(); - new CalendarOutputter(false).output(calendar, response.getOutputStream()); + outputCalendar(calendar, request, response); } } else { response.sendError(HttpServletResponse.SC_NOT_FOUND, requestUrl); @@ -241,6 +242,59 @@ public class ICalServlet extends HttpServlet { httpResponse.setHeader("Cache-Control", "max-age="+ cacheAge); } + private void outputCalendar(Calendar calendar, HttpServletRequest request, HttpServletResponse response) + throws ValidationException, IOException { + boolean outlook = isOutlook(request); + updateUrlProperties(calendar); + + Writer out = response.getWriter(); + out.write(Calendar.BEGIN); + out.write(':'); + out.write(Calendar.VCALENDAR); + out.write(Strings.LINE_SEPARATOR); + out.write(Version.VERSION_2_0.toString()); + + boolean calScale = false; + for (Iterator<?> propIter = calendar.getProperties().iterator(); propIter.hasNext();) { + Object pobject = propIter.next(); + if(pobject instanceof Property) { + Property property = (Property)pobject; + if(Version.VERSION.equals(property.getName())) { + //we force version 2.0 + } else if(Version.CALSCALE.equals(property.getName())) { + out.write(property.toString()); + calScale = true; + } else { + out.write(property.toString()); + } + } + } + + if(!calScale) { + out.write(CalScale.GREGORIAN.toString()); + } + + outputTTL(out); + + Set<String> timezoneIds = new HashSet<>(); + outputCalendarComponents(calendar, out, outlook, timezoneIds); + if(outlook) { + outputTimeZoneForOutlook(timezoneIds, out); + } + + out.write(Calendar.END); + out.write(':'); + out.write(Calendar.VCALENDAR); + } + + /** + * Collect all the calendars, update the URL properties and the UUID. + * + * @param identity + * @param request + * @param response + * @throws IOException + */ private void generateAggregatedCalendar(Identity identity, HttpServletRequest request, HttpServletResponse response) throws IOException { PersonalCalendarManager homeCalendarManager = CoreSpringFactory.getImpl(PersonalCalendarManager.class); if(identity == null) { @@ -257,6 +311,8 @@ public class ICalServlet extends HttpServlet { out.write(Strings.LINE_SEPARATOR); out.write(Version.VERSION_2_0.toString()); out.write(CalScale.GREGORIAN.toString()); + + outputTTL(out); Set<String> timezoneIds = new HashSet<>(); int numOfFiles = iCalFiles.size(); @@ -281,6 +337,22 @@ public class ICalServlet extends HttpServlet { return false; } + /** + * Append TTL:<br> + * @see http://stackoverflow.com/questions/17152251/specifying-name-description-and-refresh-interval-in-ical-ics-format + * @see http://tools.ietf.org/html/draft-daboo-icalendar-extensions-06 + * + * @param out + * @throws IOException + */ + private void outputTTL(Writer out) + throws IOException { + out.write("X-PUBLISHED-TTL:PT" + TTL_HOURS + "H"); + out.write(Strings.LINE_SEPARATOR); + out.write("REFRESH-INTERVAL;VALUE=DURATION:PT" + TTL_HOURS + "H"); + out.write(Strings.LINE_SEPARATOR); + } + private void outputTimeZoneForOutlook(Set<String> timezoneIds, Writer out) { for(String timezoneId:timezoneIds) { if(StringHelper.containsNonWhitespace(timezoneId)) { @@ -306,6 +378,15 @@ public class ICalServlet extends HttpServlet { String prefix = fileInfos.getType() + "-" + fileInfos.getCalendarId() + "-"; updateUUID(calendar, prefix); + outputCalendarComponents(calendar, out, outlook, timezoneIds); + } catch (IOException | OLATRuntimeException e) { + log.error("", e); + } + } + + private void outputCalendarComponents(Calendar calendar, Writer out, boolean outlook, Set<String> timezoneIds) + throws IOException { + try { ComponentList events = calendar.getComponents(); for (final Iterator<?> i = events.iterator(); i.hasNext();) { Object comp = i.next(); diff --git a/src/main/java/org/olat/commons/calendar/manager/ICalFileCalendarManager.java b/src/main/java/org/olat/commons/calendar/manager/ICalFileCalendarManager.java index c1bc8998223..78faf4d1455 100644 --- a/src/main/java/org/olat/commons/calendar/manager/ICalFileCalendarManager.java +++ b/src/main/java/org/olat/commons/calendar/manager/ICalFileCalendarManager.java @@ -244,9 +244,10 @@ public class ICalFileCalendarManager implements CalendarManager, InitializingBea return cal; } - /** - * Internal read calendar file from filesystem - */ + /** + * Internal read calendar file from filesystem. It doesn't + * use the cache and return a not shared calendar. + */ @Override public Calendar readCalendar(String type, String calendarID) { if(log.isDebug()) { -- GitLab