PatchDocbookMojo.java
package network.ike.docs.plugin;
import org.apache.maven.api.plugin.MojoException;
import org.apache.maven.api.plugin.annotations.Mojo;
import org.apache.maven.api.plugin.annotations.Parameter;
import java.io.File;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.Path;
/**
* Patch stock DocBook XSL stylesheets to suppress Saxon warnings.
*
* <p>Applies two targeted fixes to the downloaded DocBook XSL 1.79.2
* distribution:
* <ol>
* <li>{@code fo/docbook.xsl} — removes the direct include of
* {@code ../common/utility.xsl} which creates a diamond import
* (Saxon SXWN9019: included or imported more than once).</li>
* <li>{@code fo/math.xsl} — removes the dead
* {@code <xsl:variable name="output.delims">} block that is
* computed but never used (Saxon SXWN9001).</li>
* </ol>
*
* <p>Replaces: {@code patch-docbook-xsl.sh}
*
* <p>Usage:
* <pre>
* mvn ike:patch-docbook -DdocbookDir=target/docbook-xsl
* </pre>
*/
@Mojo(name = "patch-docbook",
defaultPhase = "generate-resources")
public class PatchDocbookMojo implements org.apache.maven.api.plugin.Mojo {
@org.apache.maven.api.di.Inject
private org.apache.maven.api.plugin.Log log;
/**
* Access the Maven logger.
*
* @return the logger
*/
protected org.apache.maven.api.plugin.Log getLog() { return log; }
/** Root directory of the unpacked DocBook XSL distribution. */
@Parameter(property = "docbookDir", required = true)
File docbookDir;
/** Creates this goal instance. */
public PatchDocbookMojo() {}
@Override
public void execute() throws MojoException {
if (!docbookDir.isDirectory()) {
getLog().info("patch-docbook: directory does not exist, skipping — "
+ docbookDir);
return;
}
// Patch fo/docbook.xsl — remove diamond utility.xsl include
Path docbookXsl = docbookDir.toPath().resolve("fo/docbook.xsl");
patchFile(docbookXsl, "utility.xsl include",
PatchDocbookMojo::removeUtilityInclude);
// Patch fo/math.xsl — remove dead output.delims variable
Path mathXsl = docbookDir.toPath().resolve("fo/math.xsl");
patchFile(mathXsl, "dead output.delims variable",
PatchDocbookMojo::removeDeadVariable);
getLog().info("patch-docbook: patched DocBook XSL in " + docbookDir);
}
/**
* Read a file, apply a transformation, and write it back.
* Logs and skips if the file does not exist.
*/
private void patchFile(Path file, String description,
java.util.function.UnaryOperator<String> transform)
throws MojoException {
if (!Files.isRegularFile(file)) {
getLog().info("patch-docbook: " + file.getFileName()
+ " not found, skipping " + description);
return;
}
try {
String content = Files.readString(file);
String patched = transform.apply(content);
if (!content.equals(patched)) {
Files.writeString(file, patched);
getLog().info("patch-docbook: removed " + description
+ " from " + file.getFileName());
}
} catch (IOException e) {
throw new MojoException(
"Failed to patch " + file, e);
}
}
// ── Pure testable functions ──────────────────────────────────────
/**
* Remove the {@code <xsl:include href="../common/utility.xsl"/>}
* line from DocBook's {@code fo/docbook.xsl}.
*
* @param xsl the XSL content
* @return patched XSL with the utility include removed
*/
public static String removeUtilityInclude(String xsl) {
return xsl.replace("<xsl:include href=\"../common/utility.xsl\"/>", "");
}
/**
* Remove the dead {@code <xsl:variable name="output.delims">}
* block from DocBook's {@code fo/math.xsl}.
*
* <p>The variable spans multiple lines and is matched with a
* non-greedy pattern from the opening tag to the closing tag.
*
* @param xsl the XSL content
* @return patched XSL with the dead variable removed
*/
public static String removeDeadVariable(String xsl) {
return xsl.replaceAll(
"(?s)<xsl:variable name=\"output\\.delims\">.*?</xsl:variable>",
"");
}
}