Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package maven-script-interpreter for 
openSUSE:Factory checked in at 2026-09-28 10:38:49
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/maven-script-interpreter (Old)
 and      /work/SRC/openSUSE:Factory/.maven-script-interpreter.new.383539 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "maven-script-interpreter"

Mon Sep 28 10:38:49 2026 rev:8 rq:1380999 version:1.9

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/maven-script-interpreter/maven-script-interpreter.changes
        2026-09-11 18:07:31.401382950 +0200
+++ 
/work/SRC/openSUSE:Factory/.maven-script-interpreter.new.383539/maven-script-interpreter.changes
    2026-09-28 10:39:58.708676810 +0200
@@ -1,0 +2,27 @@
+Sun Sep 27 20:16:44 UTC 2026 - Fridrich Strba <[email protected]>
+
+- Upgrade to version 1.9
+  * Maven Script Interpreter 1.9 fixes how scripts run under the
+    Maven Invoker Plugin: the basedir variable, Groovy class
+    loading, and script encoding.
+  * Behaviour changes:
+    + The basedir script variable is now the project directory, as
+      the invoker plugin documentation describes. Before, it was the
+      directory holding the script, so the two differed for scripts
+      in a subdirectory. Scripts that need their own directory can
+      use the new scriptdir variable.
+    + Without an explicit encoding, scripts are read as UTF-8
+      instead of the platform default charset.
+  * Bug fixes
+    + Bind the basedir script variable to the project directory and
+      add scriptdir
+    + Load Groovy's own classes parent-first, so a different Groovy
+      version on the caller's class path no longer breaks compiled
+      scripts
+    + Read scripts as UTF-8 when no encoding is set
+    + FileLogger: fix the NullPointerException for a log file with
+      no parent directory
+  * Maintenance
+    + Test that a failing script throws an exception
+
+-------------------------------------------------------------------

Old:
----
  maven-script-interpreter-1.8-source-release.zip

New:
----
  maven-script-interpreter-1.9-source-release.zip

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ maven-script-interpreter.spec ++++++
--- /var/tmp/diff_new_pack.Xab6Sm/_old  2026-09-28 10:40:03.424874574 +0200
+++ /var/tmp/diff_new_pack.Xab6Sm/_new  2026-09-28 10:40:03.425874616 +0200
@@ -17,7 +17,7 @@
 
 
 Name:           maven-script-interpreter
-Version:        1.8
+Version:        1.9
 Release:        0
 Summary:        Maven Script Interpreter
 License:        Apache-2.0
@@ -68,8 +68,7 @@
     slf4j/api \
     slf4j/simple
 
-%{ant} \
-       jar javadoc
+ant jar javadoc
 
 %install
 # jar

++++++ _scmsync.obsinfo ++++++
--- /var/tmp/diff_new_pack.Xab6Sm/_old  2026-09-28 10:40:03.458876000 +0200
+++ /var/tmp/diff_new_pack.Xab6Sm/_new  2026-09-28 10:40:03.461876125 +0200
@@ -1,6 +1,6 @@
-mtime: 1788616025
-commit: f970277aa145567fd6ff760715b2196da327cd2ee04d2c34b1490d492ac229df
+mtime: 1790540624
+commit: 3a2fe120a66000db30a86d430d8c631814030e2835adf4b0105732c7cea08887
 url: https://src.opensuse.org/java-packages/maven-script-interpreter
-revision: f970277aa145567fd6ff760715b2196da327cd2ee04d2c34b1490d492ac229df
+revision: 3a2fe120a66000db30a86d430d8c631814030e2835adf4b0105732c7cea08887
 projectscmsync: https://src.opensuse.org/java-packages/_ObsPrj
 

++++++ build.specials.obscpio ++++++

++++++ build.specials.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/.gitignore new/.gitignore
--- old/.gitignore      1970-01-01 01:00:00.000000000 +0100
+++ new/.gitignore      2026-09-27 22:23:44.000000000 +0200
@@ -0,0 +1 @@
+.osc

++++++ maven-script-interpreter-1.8-source-release.zip -> 
maven-script-interpreter-1.9-source-release.zip ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/maven-script-interpreter-1.8/pom.xml 
new/maven-script-interpreter-1.9/pom.xml
--- old/maven-script-interpreter-1.8/pom.xml    2026-09-01 06:09:38.000000000 
+0200
+++ new/maven-script-interpreter-1.9/pom.xml    2026-09-19 14:17:02.000000000 
+0200
@@ -27,7 +27,7 @@
   </parent>
 
   <artifactId>maven-script-interpreter</artifactId>
-  <version>1.8</version>
+  <version>1.9</version>
 
   <name>Apache Maven Script Interpreter</name>
   <description>This component provides some utilities to interpret/execute 
some scripts for various implementations:
@@ -36,7 +36,7 @@
   <scm>
     
<connection>scm:git:https://gitbox.apache.org/repos/asf/maven-script-interpreter.git</connection>
     
<developerConnection>scm:git:https://gitbox.apache.org/repos/asf/maven-script-interpreter.git</developerConnection>
-    <tag>maven-script-interpreter-1.8</tag>
+    <tag>maven-script-interpreter-1.9</tag>
     
<url>https://github.com/apache/maven-script-interpreter/tree/${project.scm.tag}</url>
   </scm>
   <issueManagement>
@@ -56,7 +56,7 @@
 
   <properties>
     <slf4j.version>1.7.36</slf4j.version>
-    
<project.build.outputTimestamp>2026-09-01T06:09:37Z</project.build.outputTimestamp>
+    
<project.build.outputTimestamp>2026-09-19T14:17:01Z</project.build.outputTimestamp>
 
   </properties>
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/maven-script-interpreter-1.8/src/main/java/org/apache/maven/shared/scriptinterpreter/FileLogger.java
 
new/maven-script-interpreter-1.9/src/main/java/org/apache/maven/shared/scriptinterpreter/FileLogger.java
--- 
old/maven-script-interpreter-1.8/src/main/java/org/apache/maven/shared/scriptinterpreter/FileLogger.java
    2026-09-01 06:09:38.000000000 +0200
+++ 
new/maven-script-interpreter-1.9/src/main/java/org/apache/maven/shared/scriptinterpreter/FileLogger.java
    2026-09-19 14:17:02.000000000 +0200
@@ -65,7 +65,10 @@
 
         if (outputFile != null) {
             Path outputPath = outputFile.toPath();
-            Files.createDirectories(outputPath.getParent());
+            Path parent = outputPath.getParent();
+            if (parent != null) {
+                Files.createDirectories(parent);
+            }
             outputStream = createOutputStream(outputPath);
         } else {
             outputStream = new NullOutputStream();
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/maven-script-interpreter-1.8/src/main/java/org/apache/maven/shared/scriptinterpreter/GroovyScriptInterpreter.java
 
new/maven-script-interpreter-1.9/src/main/java/org/apache/maven/shared/scriptinterpreter/GroovyScriptInterpreter.java
--- 
old/maven-script-interpreter-1.8/src/main/java/org/apache/maven/shared/scriptinterpreter/GroovyScriptInterpreter.java
       2026-09-01 06:09:38.000000000 +0200
+++ 
new/maven-script-interpreter-1.9/src/main/java/org/apache/maven/shared/scriptinterpreter/GroovyScriptInterpreter.java
       2026-09-19 14:17:02.000000000 +0200
@@ -39,8 +39,55 @@
  */
 class GroovyScriptInterpreter implements ScriptInterpreter {
 
-    private final RootLoader childFirstLoader =
-            new RootLoader(new URL[] {}, 
Thread.currentThread().getContextClassLoader());
+    /**
+     * A child-first class loader that makes one exception: Groovy's own 
classes always come from the parent. The
+     * scripts are compiled by the Groovy runtime on the parent class path, so 
a Groovy of a different version on the
+     * caller-supplied class path would otherwise shadow it and the compiled 
script could not be cast to
+     * {@link groovy.lang.GroovyObject}.
+     */
+    static class GroovyParentFirstRootLoader extends RootLoader {
+
+        GroovyParentFirstRootLoader(ClassLoader parent) {
+            super(new URL[] {}, parent);
+        }
+
+        /**
+         * Indicates whether the given class belongs to the Groovy runtime and 
must therefore be loaded from the
+         * parent class loader.
+         *
+         * @param name The binary name of the class, must not be 
<code>null</code>.
+         * @return <code>true</code> if the class must be loaded parent-first.
+         */
+        static boolean isGroovyRuntimeClass(String name) {
+            return name.startsWith("groovy.")
+                    || name.startsWith("org.codehaus.groovy.")
+                    || name.startsWith("org.apache.groovy.");
+        }
+
+        @Override
+        protected synchronized Class<?> loadClass(String name, boolean 
resolve) throws ClassNotFoundException {
+            if (isGroovyRuntimeClass(name)) {
+                Class<?> c = findLoadedClass(name);
+                if (c == null && getParent() != null) {
+                    try {
+                        c = getParent().loadClass(name);
+                    } catch (ClassNotFoundException e) {
+                        // not provided by the parent, fall back to the 
regular child-first lookup
+                    }
+                }
+                if (c != null) {
+                    if (resolve) {
+                        resolveClass(c);
+                    }
+                    return c;
+                }
+            }
+            return super.loadClass(name, resolve);
+        }
+    }
+
+    private final GroovyParentFirstRootLoader childFirstLoader =
+            new 
GroovyParentFirstRootLoader(Thread.currentThread().getContextClassLoader());
 
     private String targetBytecode;
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/maven-script-interpreter-1.8/src/main/java/org/apache/maven/shared/scriptinterpreter/ScriptRunner.java
 
new/maven-script-interpreter-1.9/src/main/java/org/apache/maven/shared/scriptinterpreter/ScriptRunner.java
--- 
old/maven-script-interpreter-1.8/src/main/java/org/apache/maven/shared/scriptinterpreter/ScriptRunner.java
  2026-09-01 06:09:38.000000000 +0200
+++ 
new/maven-script-interpreter-1.9/src/main/java/org/apache/maven/shared/scriptinterpreter/ScriptRunner.java
  2026-09-19 14:17:02.000000000 +0200
@@ -22,6 +22,7 @@
 import java.io.File;
 import java.io.IOException;
 import java.io.PrintStream;
+import java.nio.charset.StandardCharsets;
 import java.nio.file.Files;
 import java.util.HashMap;
 import java.util.LinkedHashMap;
@@ -56,7 +57,7 @@
     private final Map<String, Object> globalVariables;
 
     /**
-     * The file encoding of the hook scripts or <code>null</code> to use 
platform encoding.
+     * The file encoding of the hook scripts or <code>null</code> to use UTF-8.
      */
     private String encoding;
 
@@ -119,8 +120,7 @@
     /**
      * Sets the file encoding of the hook scripts.
      *
-     * @param encoding The file encoding of the hook scripts, may be 
<code>null</code> or empty to use the platform's
-     *                 default encoding.
+     * @param encoding The file encoding of the hook scripts, may be 
<code>null</code> or empty to use UTF-8.
      */
     public void setScriptEncoding(String encoding) {
         this.encoding = encoding != null && !encoding.isEmpty() ? encoding : 
null;
@@ -128,6 +128,10 @@
 
     /**
      * Runs the specified hook script (after resolution).
+     * <p>
+     * The script is given the global variables <code>basedir</code>, holding 
the project base directory passed in
+     * here, and <code>scriptdir</code>, holding the directory the script file 
itself lives in. The two differ when
+     * <code>relativeScriptPath</code> points into a subdirectory of the 
project.
      *
      * @param scriptDescription The description of the script to use for 
logging, must not be <code>null</code>.
      * @param basedir The base directory of the project, must not be 
<code>null</code>.
@@ -161,11 +165,14 @@
             return;
         }
 
-        executeRun(scriptDescription, scriptFile, context, logger);
+        executeRun(scriptDescription, basedir, scriptFile, context, logger);
     }
 
     /**
      * Runs the specified hook script.
+     * <p>
+     * As no project base directory is passed in, both the 
<code>basedir</code> and the <code>scriptdir</code> global
+     * variables are set to the directory the script file lives in.
      *
      * @param scriptDescription The description of the script to use for 
logging, must not be <code>null</code>.
      * @param scriptFile The path to the script, may be <code>null</code> to 
skip the script execution.
@@ -183,11 +190,15 @@
             return;
         }
 
-        executeRun(scriptDescription, scriptFile, context, logger);
+        executeRun(scriptDescription, scriptFile.getParentFile(), scriptFile, 
context, logger);
     }
 
     private void executeRun(
-            final String scriptDescription, File scriptFile, final Map<String, 
?> context, final ExecutionLogger logger)
+            final String scriptDescription,
+            final File basedir,
+            File scriptFile,
+            final Map<String, ?> context,
+            final ExecutionLogger logger)
             throws IOException, ScriptException {
         ScriptInterpreter interpreter = getInterpreter(scriptFile);
         if (LOG.isDebugEnabled()) {
@@ -202,7 +213,7 @@
             if (encoding != null) {
                 script = new String(bytes, encoding);
             } else {
-                script = new String(bytes);
+                script = new String(bytes, StandardCharsets.UTF_8);
             }
         } catch (IOException e) {
             String errorMessage =
@@ -219,7 +230,8 @@
             PrintStream out = (logger != null) ? logger.getPrintStream() : 
null;
 
             Map<String, Object> scriptVariables = new 
HashMap<>(this.globalVariables);
-            scriptVariables.put("basedir", scriptFile.getParentFile());
+            scriptVariables.put("basedir", basedir);
+            scriptVariables.put("scriptdir", scriptFile.getParentFile());
             scriptVariables.put("context", context);
 
             synchronized (LOCK) {
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/maven-script-interpreter-1.8/src/site/markdown/index.md.vm 
new/maven-script-interpreter-1.9/src/site/markdown/index.md.vm
--- old/maven-script-interpreter-1.8/src/site/markdown/index.md.vm      
2026-09-01 06:09:38.000000000 +0200
+++ new/maven-script-interpreter-1.9/src/site/markdown/index.md.vm      
2026-09-19 14:17:02.000000000 +0200
@@ -84,9 +84,12 @@
 
 #[[### Global variables]]#
 
-Your scripts will have by default two global variables:
+Your scripts will have by default three global variables:
 
-- `basedir`: the base directory of your script
+- `basedir`: the base directory passed to `run(...)`, which is the project 
directory. For the `run(...)` overload that
+  takes a script file and no base directory, it is the directory containing 
the script.
+- `scriptdir`: the directory containing the script, which differs from 
`basedir` when the script lives in a
+  subdirectory of the project
 - `context`: the build context (see below)
 
 You can add more global variables as it.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/maven-script-interpreter-1.8/src/test/java/org/apache/maven/shared/scriptinterpreter/FileLoggerTest.java
 
new/maven-script-interpreter-1.9/src/test/java/org/apache/maven/shared/scriptinterpreter/FileLoggerTest.java
--- 
old/maven-script-interpreter-1.8/src/test/java/org/apache/maven/shared/scriptinterpreter/FileLoggerTest.java
        2026-09-01 06:09:38.000000000 +0200
+++ 
new/maven-script-interpreter-1.9/src/test/java/org/apache/maven/shared/scriptinterpreter/FileLoggerTest.java
        2026-09-19 14:17:02.000000000 +0200
@@ -109,4 +109,24 @@
         assertTrue(outputFile.exists());
         assertEquals(EXPECTED_LOG, new 
String(Files.readAllBytes(outputFile.toPath())));
     }
+
+    @Test
+    void bareFilenameNoParent() throws Exception {
+        File outputFile = new File("filelogger-204-bare.log");
+        assertNull(outputFile.getParent());
+        try {
+            try (FileLogger fileLogger = new FileLogger(outputFile)) {
+                fileLogger.consumeLine("Test1");
+                fileLogger.getPrintStream().println("Test2");
+                fileLogger.getPrintStream().flush();
+
+                assertEquals(outputFile, fileLogger.getOutputFile());
+            }
+
+            assertTrue(outputFile.exists());
+            assertEquals(EXPECTED_LOG, new 
String(Files.readAllBytes(outputFile.toPath())));
+        } finally {
+            Files.deleteIfExists(outputFile.toPath());
+        }
+    }
 }
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/maven-script-interpreter-1.8/src/test/java/org/apache/maven/shared/scriptinterpreter/GroovyScriptInterpreterTest.java
 
new/maven-script-interpreter-1.9/src/test/java/org/apache/maven/shared/scriptinterpreter/GroovyScriptInterpreterTest.java
--- 
old/maven-script-interpreter-1.8/src/test/java/org/apache/maven/shared/scriptinterpreter/GroovyScriptInterpreterTest.java
   2026-09-01 06:09:38.000000000 +0200
+++ 
new/maven-script-interpreter-1.9/src/test/java/org/apache/maven/shared/scriptinterpreter/GroovyScriptInterpreterTest.java
   2026-09-19 14:17:02.000000000 +0200
@@ -18,17 +18,28 @@
  */
 package org.apache.maven.shared.scriptinterpreter;
 
+import javax.tools.JavaCompiler;
+import javax.tools.ToolProvider;
+
 import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.PrintStream;
+import java.nio.charset.StandardCharsets;
+import java.nio.file.Files;
 import java.util.Collections;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 
+import org.apache.commons.io.FilenameUtils;
 import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.io.TempDir;
 
 import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.junit.jupiter.api.Assertions.assertNotSame;
+import static org.junit.jupiter.api.Assertions.assertSame;
+import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assumptions.assumeTrue;
 
 /**
  * Tests the Groovy interpreter facade.
@@ -36,6 +47,10 @@
  * @author Benjamin Bentmann
  */
 class GroovyScriptInterpreterTest {
+
+    @TempDir
+    private File tempDir;
+
     @Test
     void evaluateScript() throws Exception {
         ByteArrayOutputStream out = new ByteArrayOutputStream();
@@ -109,6 +124,93 @@
         assertEquals("Test", out.toString());
     }
 
+    /**
+     * A Groovy of a different version on the caller-supplied class path must 
not shadow the Groovy the scripts are
+     * compiled with, while every other class stays child-first.
+     *
+     * @see <a 
href="https://github.com/apache/maven-invoker-plugin/issues/642";>maven-invoker-plugin#642</a>
+     */
+    @Test
+    void groovyClassesAreLoadedParentFirstOtherClassesChildFirst() throws 
Exception {
+        File classesDir = compileShadowClasses();
+
+        try (GroovyScriptInterpreter.GroovyParentFirstRootLoader loader =
+                new GroovyScriptInterpreter.GroovyParentFirstRootLoader(
+                        getClass().getClassLoader())) {
+            loader.addURL(classesDir.toURI().toURL());
+
+            assertSame(groovy.lang.Binding.class, 
loader.loadClass("groovy.lang.Binding"));
+
+            Class<?> shadowed = 
loader.loadClass(FilenameUtils.class.getName());
+            assertNotSame(FilenameUtils.class, shadowed);
+            assertSame(loader, shadowed.getClassLoader());
+        }
+    }
+
+    /**
+     * A script must still compile and run when a stale Groovy sits on the 
supplied class path.
+     */
+    @Test
+    void evaluateScriptWithShadowedGroovyOnClassPath() throws Exception {
+        File classesDir = compileShadowClasses();
+
+        ByteArrayOutputStream out = new ByteArrayOutputStream();
+        try (ScriptInterpreter interpreter = new GroovyScriptInterpreter()) {
+            
interpreter.setClassPath(Collections.singletonList(classesDir.getAbsolutePath()));
+            assertEquals(
+                    Boolean.TRUE,
+                    interpreter.evaluateScript("print \"Test\"\nreturn true", 
null, new PrintStream(out)));
+        }
+        assertEquals("Test", out.toString());
+    }
+
+    /**
+     * Compiles stripped-down copies of <code>groovy.lang.Binding</code>, 
<code>groovy.lang.Script</code> and
+     * <code>org.apache.commons.io.FilenameUtils</code>, all of which also 
exist on the parent class path, into a
+     * directory usable as an additional class path entry. This stands in for 
the incompatible Groovy version that
+     * <code>addTestClassPath</code> puts in front of the interpreter's own.
+     */
+    private File compileShadowClasses() throws Exception {
+        JavaCompiler compiler = ToolProvider.getSystemJavaCompiler();
+        assumeTrue(compiler != null, "JDK compiler is not available");
+
+        File sourceDir = new File(tempDir, "src");
+        File classesDir = new File(tempDir, "classes");
+        assertTrue(classesDir.mkdirs() || classesDir.isDirectory());
+
+        File binding = writeSource(
+                sourceDir, "groovy/lang/Binding.java", "package 
groovy.lang;\n\npublic class Binding {\n}\n");
+        File script =
+                writeSource(sourceDir, "groovy/lang/Script.java", "package 
groovy.lang;\n\npublic class Script {\n}\n");
+        File filenameUtils = writeSource(
+                sourceDir,
+                "org/apache/commons/io/FilenameUtils.java",
+                "package org.apache.commons.io;\n\npublic class FilenameUtils 
{\n}\n");
+
+        assertTrue(
+                compiler.run(
+                                null,
+                                null,
+                                null,
+                                "-d",
+                                classesDir.getAbsolutePath(),
+                                binding.getAbsolutePath(),
+                                script.getAbsolutePath(),
+                                filenameUtils.getAbsolutePath())
+                        == 0,
+                "compilation of the shadowing classes failed");
+
+        return classesDir;
+    }
+
+    private File writeSource(File sourceDir, String relativePath, String 
content) throws Exception {
+        File sourceFile = new File(sourceDir, relativePath);
+        assertTrue(sourceFile.getParentFile().mkdirs()
+                || sourceFile.getParentFile().isDirectory());
+        Files.write(sourceFile.toPath(), 
content.getBytes(StandardCharsets.UTF_8));
+        return sourceFile;
+    }
+
     @Test
     void normalizeTargetBytecodeMapsOldJdksToDotForm() {
         assertEquals("1.4", 
GroovyScriptInterpreter.normalizeTargetBytecode("4"));
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/maven-script-interpreter-1.8/src/test/java/org/apache/maven/shared/scriptinterpreter/ScriptRunnerTest.java
 
new/maven-script-interpreter-1.9/src/test/java/org/apache/maven/shared/scriptinterpreter/ScriptRunnerTest.java
--- 
old/maven-script-interpreter-1.8/src/test/java/org/apache/maven/shared/scriptinterpreter/ScriptRunnerTest.java
      2026-09-01 06:09:38.000000000 +0200
+++ 
new/maven-script-interpreter-1.9/src/test/java/org/apache/maven/shared/scriptinterpreter/ScriptRunnerTest.java
      2026-09-19 14:17:02.000000000 +0200
@@ -32,6 +32,7 @@
 import static org.junit.jupiter.api.Assertions.assertEquals;
 import static org.junit.jupiter.api.Assertions.assertNotNull;
 import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.junit.jupiter.api.Assertions.fail;
 
 /**
  * @author Olivier Lamy
@@ -81,44 +82,35 @@
     @Test
     void failedBeanshellShouldCreateProperLogsMessage() throws Exception {
         File logFile = new File(tempDir, "build.log");
-
         TestMirrorHandler mirrorHandler = new TestMirrorHandler();
 
-        Exception catchedException = null;
-
         try (FileLogger fileLogger = new FileLogger(logFile, mirrorHandler);
                 ScriptRunner scriptRunner = new ScriptRunner()) {
             scriptRunner.run("test", new File("src/test/resources/bsh-test"), 
"failed", buildContext(), fileLogger);
-        } catch (ScriptEvaluationException e) {
-            catchedException = e;
+            fail();
+        } catch (ScriptEvaluationException expected) {
+            String logContent = new 
String(Files.readAllBytes(logFile.toPath()));
+            assertTrue(logContent.contains(new 
File("src/test/resources/bsh-test/failed.bsh").getPath()));
+            assertEquals(logContent, mirrorHandler.getLoggedMessage());
         }
-
-        assertNotNull(catchedException);
-        String logContent = new String(Files.readAllBytes(logFile.toPath()));
-        assertTrue(logContent.contains(new 
File("src/test/resources/bsh-test/failed.bsh").getPath()));
-        assertEquals(logContent, mirrorHandler.getLoggedMessage());
     }
 
     @Test
     void beanshellReturnedNotTrueShouldThrowException() throws Exception {
         File logFile = new File(tempDir, "build.log");
-
         TestMirrorHandler mirrorHandler = new TestMirrorHandler();
 
-        ScriptReturnException catchedException = null;
-
         try (FileLogger fileLogger = new FileLogger(logFile, mirrorHandler);
                 ScriptRunner scriptRunner = new ScriptRunner()) {
             scriptRunner.run("test", new File("src/test/resources/bsh-test"), 
"return-not-true", null, fileLogger);
-        } catch (ScriptReturnException e) {
-            catchedException = e;
+            fail();
+        } catch (ScriptReturnException expected) {
+            assertEquals("Not true value", expected.getResult());
+            assertEquals("The test returned Not true value.", 
expected.getMessage());
+            String logContent = new 
String(Files.readAllBytes(logFile.toPath()));
+            assertTrue(logContent.contains(new 
File("src/test/resources/bsh-test/return-not-true.bsh").getPath()));
+            assertEquals(logContent, mirrorHandler.getLoggedMessage());
         }
-
-        assertEquals("Not true value", catchedException.getResult());
-        assertEquals("The test returned Not true value.", 
catchedException.getMessage());
-        String logContent = new String(Files.readAllBytes(logFile.toPath()));
-        assertTrue(logContent.contains(new 
File("src/test/resources/bsh-test/return-not-true.bsh").getPath()));
-        assertEquals(logContent, mirrorHandler.getLoggedMessage());
     }
 
     @Test
@@ -181,45 +173,34 @@
     @Test
     void failedGroovyShouldCreateProperLogsMessage() throws Exception {
         File logFile = new File(tempDir, "build.log");
-
         TestMirrorHandler mirrorHandler = new TestMirrorHandler();
 
-        Exception catchedException = null;
-
         try (FileLogger fileLogger = new FileLogger(logFile, mirrorHandler);
                 ScriptRunner scriptRunner = new ScriptRunner()) {
             scriptRunner.run("test", new 
File("src/test/resources/groovy-test"), "failed", buildContext(), fileLogger);
-        } catch (ScriptEvaluationException e) {
-            catchedException = e;
+        } catch (ScriptEvaluationException expected) {
+            String logContent = new 
String(Files.readAllBytes(logFile.toPath()));
+            assertTrue(logContent.contains(new 
File("src/test/resources/groovy-test/failed.groovy").getPath()));
+            assertEquals(logContent, mirrorHandler.getLoggedMessage());
         }
-
-        assertNotNull(catchedException);
-        String logContent = new String(Files.readAllBytes(logFile.toPath()));
-        assertTrue(logContent.contains(new 
File("src/test/resources/groovy-test/failed.groovy").getPath()));
-        assertEquals(logContent, mirrorHandler.getLoggedMessage());
     }
 
     @Test
     void groovyReturnedFalseShouldThrowException() throws Exception {
         File logFile = new File(tempDir, "build.log");
-
         TestMirrorHandler mirrorHandler = new TestMirrorHandler();
 
-        ScriptReturnException catchedException = null;
-
         try (FileLogger fileLogger = new FileLogger(logFile, mirrorHandler);
                 ScriptRunner scriptRunner = new ScriptRunner()) {
             scriptRunner.run(
                     "test", new File("src/test/resources/groovy-test"), 
"return-false", buildContext(), fileLogger);
-        } catch (ScriptReturnException e) {
-            catchedException = e;
+        } catch (ScriptReturnException expected) {
+            assertEquals(false, expected.getResult());
+            assertEquals("The test returned false.", expected.getMessage());
+            String logContent = new 
String(Files.readAllBytes(logFile.toPath()));
+            assertTrue(logContent.contains(new 
File("src/test/resources/groovy-test/return-false.groovy").getPath()));
+            assertEquals(logContent, mirrorHandler.getLoggedMessage());
         }
-
-        assertEquals(false, catchedException.getResult());
-        assertEquals("The test returned false.", 
catchedException.getMessage());
-        String logContent = new String(Files.readAllBytes(logFile.toPath()));
-        assertTrue(logContent.contains(new 
File("src/test/resources/groovy-test/return-false.groovy").getPath()));
-        assertEquals(logContent, mirrorHandler.getLoggedMessage());
     }
 
     @Test
@@ -264,6 +245,75 @@
         assertTrue(logContent.contains("wireMockServer stopped"));
     }
 
+    /**
+     * A script living in a subdirectory of the project must still see the 
project directory as <code>basedir</code>,
+     * with its own directory available as <code>scriptdir</code>.
+     *
+     * @see <a 
href="https://github.com/apache/maven-invoker-plugin/issues/299";>maven-invoker-plugin#299</a>
+     */
+    @ValueSource(strings = {"bsh", "groovy"})
+    @ParameterizedTest
+    void scriptInSubDirectoryShouldSeeProjectBasedir(String scriptType) throws 
Exception {
+        File logFile = new File(tempDir, "build.log");
+        File basedir = new File("src/test/resources/basedir-test");
+
+        Map<String, Object> context = new HashMap<>();
+
+        try (FileLogger logger = new FileLogger(logFile);
+                ScriptRunner scriptRunner = new ScriptRunner()) {
+            scriptRunner.run("test", basedir, "scripts/verify." + scriptType, 
context, logger);
+        }
+
+        assertEquals(basedir, context.get("basedir"));
+        assertEquals(new File(basedir, "scripts"), context.get("scriptdir"));
+    }
+
+    /**
+     * The overload without a project directory has no better candidate, so 
both variables point at the script's own
+     * directory.
+     */
+    @ValueSource(strings = {"bsh", "groovy"})
+    @ParameterizedTest
+    void scriptRunWithoutBasedirShouldUseScriptDirectory(String scriptType) 
throws Exception {
+        File logFile = new File(tempDir, "build.log");
+        File scriptDir = new File("src/test/resources/basedir-test/scripts");
+
+        Map<String, Object> context = new HashMap<>();
+
+        try (FileLogger logger = new FileLogger(logFile);
+                ScriptRunner scriptRunner = new ScriptRunner()) {
+            scriptRunner.run("test", new File(scriptDir, "verify." + 
scriptType), context, logger);
+        }
+
+        assertEquals(scriptDir, context.get("basedir"));
+        assertEquals(scriptDir, context.get("scriptdir"));
+    }
+
+    /**
+     * Verifies that a Groovy script containing non-ASCII characters (UTF-8 
encoded)
+     * is decoded correctly when no explicit encoding is set. The script file
+     * utf8-test.groovy contains the UTF-8 string literal "café" and asserts it
+     * matches the expected value, returning true on success.
+     *
+     * @see <a 
href="https://github.com/apache/maven-script-interpreter/issues/206";>#206</a>
+     */
+    @Test
+    void groovyUtf8ScriptShouldDecodeCorrectly() throws Exception {
+        File logFile = new File(tempDir, "build.log");
+
+        Map<String, Object> context = new HashMap<>();
+        context.put("expected", "café");
+
+        try (FileLogger logger = new FileLogger(logFile);
+                ScriptRunner scriptRunner = new ScriptRunner()) {
+            scriptRunner.run("utf8-test", new 
File("src/test/resources/groovy-test/utf8-test.groovy"), context, logger);
+        }
+
+        String logContent = new String(Files.readAllBytes(logFile.toPath()));
+        assertTrue(logContent.contains("expected=café"));
+        assertTrue(logContent.contains("actual=café"));
+    }
+
     private Map<String, ?> buildContext() {
         Map<String, Object> context = new HashMap<>();
         context.put("foo", "bar");
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/maven-script-interpreter-1.8/src/test/resources/basedir-test/scripts/verify.bsh
 
new/maven-script-interpreter-1.9/src/test/resources/basedir-test/scripts/verify.bsh
--- 
old/maven-script-interpreter-1.8/src/test/resources/basedir-test/scripts/verify.bsh
 1970-01-01 01:00:00.000000000 +0100
+++ 
new/maven-script-interpreter-1.9/src/test/resources/basedir-test/scripts/verify.bsh
 2026-09-19 14:17:02.000000000 +0200
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+context.put("basedir", basedir);
+context.put("scriptdir", scriptdir);
+
+return true;
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/maven-script-interpreter-1.8/src/test/resources/basedir-test/scripts/verify.groovy
 
new/maven-script-interpreter-1.9/src/test/resources/basedir-test/scripts/verify.groovy
--- 
old/maven-script-interpreter-1.8/src/test/resources/basedir-test/scripts/verify.groovy
      1970-01-01 01:00:00.000000000 +0100
+++ 
new/maven-script-interpreter-1.9/src/test/resources/basedir-test/scripts/verify.groovy
      2026-09-19 14:17:02.000000000 +0200
@@ -0,0 +1,23 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+context.put("basedir", basedir)
+context.put("scriptdir", scriptdir)
+
+return true
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' 
old/maven-script-interpreter-1.8/src/test/resources/groovy-test/utf8-test.groovy
 
new/maven-script-interpreter-1.9/src/test/resources/groovy-test/utf8-test.groovy
--- 
old/maven-script-interpreter-1.8/src/test/resources/groovy-test/utf8-test.groovy
    1970-01-01 01:00:00.000000000 +0100
+++ 
new/maven-script-interpreter-1.9/src/test/resources/groovy-test/utf8-test.groovy
    2026-09-19 14:17:02.000000000 +0200
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+def result = context.get("expected")
+assert result != null
+System.out.println("expected=" + result)
+
+def actual = "café"
+System.out.println("actual=" + actual)
+
+return result.equals(actual)

++++++ maven-script-interpreter-build.xml ++++++
--- /var/tmp/diff_new_pack.Xab6Sm/_old  2026-09-28 10:40:03.652884135 +0200
+++ /var/tmp/diff_new_pack.Xab6Sm/_new  2026-09-28 10:40:03.655884261 +0200
@@ -10,7 +10,7 @@
 
   <property name="project.groupId" value="org.apache.maven.shared"/>
   <property name="project.artifactId" value="maven-script-interpreter"/>
-  <property name="project.version" value="1.8"/>
+  <property name="project.version" value="1.9"/>
   <property name="project.name" value="Apache Maven Script Interpreter"/>
   <property name="project.organization.name" value="The Apache Software 
Foundation"/>
 

Reply via email to