* The implementation creates a new thread. - * Since this task is started only once for a built, which is usually a few minutes typically, there is no need to use any executor service or virtual thread. + * Since this task is started only once for a built, which is usually a few minutes typically, there is no need to use any executor service. * - * @param project is the root of the project directory provided by Jamal + * @param projectDirectory is the root of the project directory provided by Jamal */ - private void convertExtensionsJam(final Path project) { + private void convertExtensionsJam(final File projectDirectory) { + createTouchFile(projectDirectory); final var t = new Thread(() -> { - final var dotMvnDir = project.resolve(".mvn"); - if (Files.exists(dotMvnDir)) { + final var dotMvnDir = new File(projectDirectory, ".mvn"); + if (dotMvnDir.exists()) { jam2Xml(dotMvnDir, "extensions", true); } }); @@ -100,11 +69,36 @@ private void convertExtensionsJam(final Path project) { t.start(); } - private void jam2Xml(final Path directory, final String sourceName, final boolean optional) { - var jamFile = directory.resolve( sourceName + ".xml.jam"); - if (!Files.exists(jamFile)) { - jamFile = directory.resolve( sourceName + ".jam"); - if (!Files.exists(jamFile)) { + /** + * Create a touch file in the .mvn directory to signal that the extension executes. + *
+ * This helps test the extension that it is compatible and runs with the actual Maven version. + * It is a piece of code that gets into production code, so it is not nice, but seems fairly harmless. + *
+ * The unit test of the extension checks that the touch file is there and that the time stamp is recent. + *
+ * The touch file must exist in the .mvn directory and its name must be 'touch'. + * It is NOT created if it does not exist, not to create garbage in real life projects. + *
+ * This functionality is not a guaranteed feature of the extension; therefore, it is not documented in the README.
+ *
+ * @param projectDirectory is the root of the project directory provided by Jamal
+ */
+ private static void createTouchFile(File projectDirectory) {
+ final var touchFile = new File(projectDirectory, ".mvn/touch");
+ if (touchFile.exists()) {
+ try {
+ Files.writeString(Paths.get(touchFile.getAbsolutePath()), System.currentTimeMillis() + "\n", StandardCharsets.UTF_8);
+ } catch (IOException ignore) {
+ }
+ }
+ }
+
+ private void jam2Xml(final File directory, final String sourceName, final boolean optional) {
+ File jamFile = new File(directory, sourceName + ".xml.jam");
+ if (!jamFile.exists()) {
+ jamFile = new File(directory, sourceName + ".jam");
+ if (!jamFile.exists()) {
if (optional) {
return;
} else {
@@ -114,7 +108,7 @@ private void jam2Xml(final Path directory, final String sourceName, final boolea
}
Processor processor = new javax0.jamal.engine.Processor();
- final String fileName = jamFile.toFile().getAbsolutePath();
+ final String fileName = jamFile.getAbsolutePath();
final String xml;
try {
xml = processor.process(FileTools.getInput(fileName, processor));
@@ -128,7 +122,7 @@ private void jam2Xml(final Path directory, final String sourceName, final boolea
throw new RuntimeException("Cannot format the file " + fileName + "\n" + dumpException(e), e);
}
- final File output = directory.resolve( sourceName + ".xml").toFile();
+ final File output = new File(directory, sourceName + ".xml");
// noinspection ResultOfMethodCallIgnored
output.setWritable(true);
try (final OutputStream os = new FileOutputStream(output)) {
@@ -173,9 +167,7 @@ private String formatOutput(String result) throws Exception {
tf.setOutputProperty(OutputKeys.INDENT, "yes");
Writer out = new StringWriter();
tf.transform(new DOMSource(doc), new StreamResult(out));
- return Arrays.stream(out.toString().split(System.lineSeparator()))
- .filter(s -> !s.trim().isEmpty())
- .collect(Collectors.joining(System.lineSeparator()));
+ return Arrays.stream(out.toString().split(System.lineSeparator())).filter(s -> s.trim().length() > 0).collect(Collectors.joining(System.lineSeparator()));
}
@Override
@@ -194,9 +186,4 @@ public Model read(Reader reader, Map
+ * The next test checks the integrity of the already DEPLOYED build.
+ * If the test fails, a fix has to be created and then a new build has to start.
+ * And that build will still use the same DEPLOYED build and will fail.
+ *
+ * To overcome this situation, this test can be executed from IntelliJ.
+ * It will create a touch file with the current timestamp.
+ * The next test will not see that the DEPLOYED build is broken and lets the current one to build and deploy.
+ *
+ *
+ * @throws IOException if the file cannot be written
+ */
+ @Test
+ @DisplayName("Create a current touch file but only in IntelliJ")
+ void createTouchFile() throws IOException {
+ }
+
@Test
- public void testNothing() {
- final var sut = new CustomModelProcessor();
+ @DisplayName("Test that the extension was running in the Jamal project")
+ public void testItWasExecuted() throws IOException {
+ final var root = DocumentConverter.getRoot();
+ final var lines = Files.readAllLines(Paths.get(root + "/.mvn", "touch"));
+ final var ts = Long.parseLong(lines.get(0)); // throw exception if not a number, fail the test
+ final var now = System.currentTimeMillis();
+ Assertions.assertTrue(ts <= now, "The touch file was not created or the timestamp is in the future");
+ if (isIntelliJ()) {
+ Assertions.assertEquals(0, ts, "We run in IntelliJ and the touch file time stamp is not zero");
+ } else {
+ Assertions.assertTrue(now - ts < 1000 * 60 * 10, "The touch file is older than 10 minutes, fix the bug, and manually run the 'createTouchFile' test from IntelliJ.");
+ }
+ // not to have a lingering current value in the touch file
+ // but write three zeroes to signal it was by the test, and not a manual reset calling
+ touch("000");
}
}
diff --git a/jamal-maven-input/pom.xml b/jamal-maven-input/pom.xml
index 771ee7c60..5194c9c1b 100644
--- a/jamal-maven-input/pom.xml
+++ b/jamal-maven-input/pom.xml
@@ -30,6 +30,7 @@