Update all the things!

Volume 4, Issue 23; 29 Mar 2020

Right then. In for a penny, in for a pound. I’ve upgraded all of the XML Calabash 1.x extensions. (And XML Calabash 1.x, come to think of it.)

XML Calabash 1.x steps are all implemented as classes on the JVM. Some of them are distributed with the processor, others are available as add-on extensions.

At runtime, the processor has to know what steps it can run, the steps for which it has implementations. There are two problems that need to be solved here: it has to be easy for implementors to specify the mapping from step type to implementation class and it has to be easy for the processor to find that mapping.

Years ago, I stumbled upon a Java class that was able to search for classes based on annotations. (If you’re not familiar with them, annotations are introduced with an “@” and you can think them as just a bit of extra metadata.) Here’s an @XMLCalabash annotation that associates steps of type ex:step-name step with the implementation class com.example.package.StepName.

package com.example.package;

import com.xmlcalabash.core.XMLCalabash;

        name = "ex:step-name",
        type = "{}step-name")

public class StepName … {

I thought that was a great idea. Implementors could decorate classes with annotations (which is both easy and keeps the declaration near the code) and the processor could find the classes by searching for the annotations.

Trouble is, it isn’t going to work in XML Calabash 2.0 3.0 because I don’t think that feature exists in Scala classes. (At least it didn’t a couple of years ago when I investigated.) Also, there was a whole kerfuffle with annotation class paths in Gradle a couple of years ago that I never really understood, and I’ve just discovered that it doesn’t work at all in a Gradle “copy filter”. I think the problem has to do with the security settings on the class loader (or something).

So I gave up, because of XML Calabash 3.0 and because I wanted to support the copy filter feature requested on stackoverflow.

What I’ve implemented instead is a much more common and universally supported feature: reading property files. Starting in XML Calabash 1.2.0, all property files named on the class path are loaded.

These property files associate steps with classes:

cx = namespace

com.xmlcalabash.extensions.StepA = step cx:step-a
com.xmlcalabash.extensions.StepB = step cx:step-b

Property files are collections of key-value pairs. The namespace prefixes and class names are used as keys. The values contain the URIs and step types, respectively.

XML Calabash 1.2.0 still (preferentially) searches for annotations, so this isn’t a backwards incompatible change.

I had to touch every one of my extension steps to add the appropriate property file and, as long as I was doing that, I figured I should update to the latest version of Gradle. (Well, almost the latest, I’m still using 6.2.2 and apparently 6.3 came out like yesterday or something.)

I’ve updated the following steps so that they build with Gradle 6.2.2:

  • AsciiDoctor (Also updated the underlying implementation to version 2.2.0)
  • DeltaXML
  • DiTAA
  • MathML-to-SVG (Also updated the underlying implementation to version 3.1.9) Note that this extension won’t compile with JDK 11 or later. The class has been removed.
  • Metadata-extractor (Also updated the underlying implementation to version 2.13.0)
  • Pegdown (Note that a CommonMark converter now ships with XML Calabash)
  • PlantUML (Also updated the underlying implementation to version 8059)
  • Print
  • Pygments
  • RDF
  • Sendmail (also updated the underlying implementation to version 1.5.2)
  • XCC (also updated the underlying implementation to version 10.0.3)
  • XMLUnitt
  • XsltHL

I’ve also updated XML Calabash to version 1.2.0. I’ll note in passing that it’s still built with Gradle 5.x because I can’t figure out how or if the “IzPack” infrastructure that builds the installer can be updated.

Share and enjoy.