Class IcsCompatibility

java.lang.Object
org.exoplatform.caldav.ics.IcsCompatibility

public final class IcsCompatibility extends Object
The one place a parser of foreign iCalendar is built, and the one place the library is told how strict to be about what other people's software writes.

Why a factory rather than a static block somewhere. ical4j reads its compatibility hints from a process-wide map at the moment a value is parsed, so a hint set in one class's static initialiser only holds for a parse that happens to run after that class was loaded. This add-on parses in four places — IcsParser, IcsReader, IcsEquivalence, IcsMerger — and the hints used to live in the static block of one of them. Routing every builder through here makes the ordering structural: a parse cannot be reached without the hints being set first.

Relaxed validation, and why it is the one that mattered. ical4j.parsing.relaxed does not reach the EMAIL parameter: net.fortuna.ical4j.model.parameter.Email's constructor runs its address through commons-validator and throws unless ical4j.validation.relaxed is on. commons-validator requires a public top-level domain, so an address on an internal mail domain — alice@stalwart.local, and equally a customer's .internal or .corp — made the whole object unreadable. Apple Calendar writes EMAIL= on the attendee line whenever its user answers an invitation, so on such a deployment every answered copy became unparseable: the answer could not be read in, and the copy could not be rewritten out either, since both directions parse the object first (EXO-89820).

What the hint reaches. On a parse path, exactly one thing: the address check in Email's constructor. Everywhere else ical4j reads it — XProperty, XComponent, the VEvent validator's rule set, CalendarValidatorImpl — it is consulted inside validate(), which this add-on never calls: eXo judges a calendar object against what it itself wrote (see IcsEquivalence), never against ical4j's RFC validator. Switching validation off therefore relaxes no check eXo was relying on.

Scope. ical4j 3.2 offers no per-parse strictness — CalendarBuilder takes no such argument — so the hints are process-wide for the classloader that holds ical4j, exactly as the relaxed-parsing hint already was. That is acceptable because the relaxation only ever widens what a reader accepts; it cannot change a byte this add-on writes.

  • Method Details

    • newCalendarBuilder

      public static net.fortuna.ical4j.data.CalendarBuilder newCalendarBuilder()
      A parser configured to read what other people's software writes.

      A fresh builder each time, deliberately: CalendarBuilder keeps per-parse state and is not safe to share between the threads a sweep runs on.

      Returns:
      a builder whose compatibility hints are already in force