You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@groovy.apache.org by pa...@apache.org on 2020/03/26 02:54:23 UTC

[groovy] branch master updated (3879511 -> a01d7fb)

This is an automated email from the ASF dual-hosted git repository.

paulk pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git.


    from 3879511  GROOVY-9479: Bump Gradle to 6.3
     new 87e342d  GROOVY-9478: Groovy Ant task could support Ant resources (closes #1204)
     new a01d7fb  GROOVY-9440: Missing line number information in stack trace (provide fallback)

The 2 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


Summary of changes:
 .../org/codehaus/groovy/classgen/ReturnAdder.java  |   2 +-
 .../main/java/org/codehaus/groovy/ant/Groovy.java  | 160 ++++++++++++++++-----
 .../groovy-ant/src/spec/doc/groovy-ant-task.adoc   |  50 ++++++-
 .../org/codehaus/groovy/ant/GroovyTest.xml         |  32 +++++
 .../groovy/org/codehaus/groovy/ant/GroovyTest.java |  40 ++++++
 5 files changed, 240 insertions(+), 44 deletions(-)


[groovy] 01/02: GROOVY-9478: Groovy Ant task could support Ant resources (closes #1204)

Posted by pa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

paulk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit 87e342d8dc5ebe22b974388e3a13f58a2c5a6cd5
Author: Paul King <pa...@asert.com.au>
AuthorDate: Wed Mar 25 16:38:06 2020 +1000

    GROOVY-9478: Groovy Ant task could support Ant resources (closes #1204)
---
 .../main/java/org/codehaus/groovy/ant/Groovy.java  | 160 ++++++++++++++++-----
 .../groovy-ant/src/spec/doc/groovy-ant-task.adoc   |  50 ++++++-
 .../org/codehaus/groovy/ant/GroovyTest.xml         |  32 +++++
 .../groovy/org/codehaus/groovy/ant/GroovyTest.java |  40 ++++++
 4 files changed, 239 insertions(+), 43 deletions(-)

diff --git a/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovy.java b/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovy.java
index 7ec8aef..12c3c96 100644
--- a/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovy.java
+++ b/subprojects/groovy-ant/src/main/java/org/codehaus/groovy/ant/Groovy.java
@@ -28,11 +28,16 @@ import groovy.util.CharsetToolkit;
 import org.apache.groovy.io.StringBuilderWriter;
 import org.apache.tools.ant.BuildException;
 import org.apache.tools.ant.Project;
+import org.apache.tools.ant.filters.util.ChainReaderHelper;
 import org.apache.tools.ant.taskdefs.Java;
 import org.apache.tools.ant.types.Commandline;
 import org.apache.tools.ant.types.FileSet;
+import org.apache.tools.ant.types.FilterChain;
 import org.apache.tools.ant.types.Path;
 import org.apache.tools.ant.types.Reference;
+import org.apache.tools.ant.types.Resource;
+import org.apache.tools.ant.types.ResourceCollection;
+import org.apache.tools.ant.types.resources.FileResource;
 import org.apache.tools.ant.util.FileUtils;
 import org.codehaus.groovy.control.CompilationFailedException;
 import org.codehaus.groovy.control.CompilerConfiguration;
@@ -42,11 +47,15 @@ import org.codehaus.groovy.runtime.InvokerHelper;
 import org.codehaus.groovy.runtime.ResourceGroovyMethods;
 import org.codehaus.groovy.tools.ErrorReporter;
 
+import java.io.BufferedInputStream;
 import java.io.BufferedOutputStream;
 import java.io.BufferedReader;
 import java.io.File;
+import java.io.FileInputStream;
 import java.io.FileOutputStream;
 import java.io.IOException;
+import java.io.InputStreamReader;
+import java.io.LineNumberReader;
 import java.io.PrintStream;
 import java.io.PrintWriter;
 import java.io.Reader;
@@ -55,6 +64,7 @@ import java.lang.reflect.Field;
 import java.nio.charset.Charset;
 import java.security.AccessController;
 import java.security.PrivilegedAction;
+import java.util.List;
 import java.util.Vector;
 
 /**
@@ -69,6 +79,11 @@ public class Groovy extends Java {
     private static final Object[] EMPTY_OBJECT_ARRAY = new Object[0];
 
     /**
+     * encoding; set to null or empty means 'default'
+     */
+    private String encoding = null;
+
+    /**
      * output encoding; set to null or empty means 'default'
      */
     private String outputEncoding = null;
@@ -81,9 +96,9 @@ public class Groovy extends Java {
     private final Vector<FileSet> filesets = new Vector<FileSet>();
 
     /**
-     * input file
+     * The input resource
      */
-    private File srcFile = null;
+    private Resource src = null;
 
     /**
      * input command
@@ -91,7 +106,7 @@ public class Groovy extends Java {
     private String command = "";
 
     /**
-     * Results Output file.
+     * Results Output file
      */
     private File output = null;
 
@@ -109,6 +124,8 @@ public class Groovy extends Java {
     private String scriptBaseClass;
     private String configscript;
 
+    private final List<FilterChain> filterChains = new Vector<>();
+
     /**
      * Compiler configuration.
      * <p>
@@ -141,6 +158,18 @@ public class Groovy extends Java {
     }
 
     /**
+     * Declare the encoding to use when inputting from a resource;
+     * If not supplied or the empty encoding is supplied, a guess will be made for file resources,
+     * otherwise the platform's default encoding will be used.
+     *
+     * @param encoding the character encoding to use.
+     * @since 3.0.3
+     */
+    public void setEncoding(String encoding) {
+        this.encoding = encoding;
+    }
+
+    /**
      * Should a new GroovyShell be used when forking. Special variables won't be available
      * but you don't need Ant in the classpath.
      *
@@ -171,12 +200,12 @@ public class Groovy extends Java {
 
     /**
      * Set the name of the file to be run. The folder of the file is automatically added to the classpath.
-     * Required unless statements are enclosed in the build file
+     * Required unless statements are enclosed in the build file or a nested resource is supplied.
      *
      * @param srcFile the file containing the groovy script to execute
      */
     public void setSrc(final File srcFile) {
-        this.srcFile = srcFile;
+        addConfigured(new FileResource(srcFile));
     }
 
     /**
@@ -186,14 +215,14 @@ public class Groovy extends Java {
      * @param txt the inline groovy commands to execute
      */
     public void addText(String txt) {
-        log("addText('" + txt + "')", Project.MSG_VERBOSE);
+        log.verbose("addText('" + txt + "')");
         this.command += txt;
     }
 
     /**
-     * Adds a set of files (nested fileset attribute).
+     * Adds a fileset (nested fileset attribute) which should represent a single source file.
      *
-     * @param set the fileset representing source files
+     * @param set the fileset representing a source file
      */
     public void addFileset(FileSet set) {
         filesets.addElement(set);
@@ -311,14 +340,28 @@ public class Groovy extends Java {
 
         command = command.trim();
 
-        if (srcFile == null && command.length() == 0 && filesets.isEmpty()) {
-            throw new BuildException("Source file does not exist!", getLocation());
+        // process filesets
+        for (FileSet next : filesets) {
+            for (Resource res : next) {
+                if (src == null) {
+                    src = res;
+                } else {
+                    throw new BuildException("A single source resource must be provided!", getLocation());
+                }
+            }
+        }
+
+        if (src == null && command.length() == 0) {
+            throw new BuildException("Source does not exist!", getLocation());
         }
 
-        if (srcFile != null && !srcFile.exists()) {
-            throw new BuildException("Source file does not exist!", getLocation());
+        if (src != null && !src.isExists()) {
+            throw new BuildException("Source resource does not exist!", getLocation());
         }
 
+        if (outputEncoding == null || outputEncoding.isEmpty()) {
+            outputEncoding = Charset.defaultCharset().name();
+        }
         try {
             PrintStream out = System.out;
             try {
@@ -326,21 +369,55 @@ public class Groovy extends Java {
                     log.verbose("Opening PrintStream to output file " + output);
                     BufferedOutputStream bos = new BufferedOutputStream(
                             new FileOutputStream(output.getAbsolutePath(), append));
-                    out = new PrintStream(bos, false,
-                            (outputEncoding == null || outputEncoding.isEmpty()) ? Charset.defaultCharset().name() : outputEncoding);
+                    out = new PrintStream(bos, false, outputEncoding);
                 }
 
                 // if there are no groovy statements between the enclosing Groovy tags
-                // then read groovy statements in from a text file using the src attribute
+                // then read groovy statements in from a resource using the src attribute
                 if (command == null || command.trim().length() == 0) {
-                    if (srcFile == null || !srcFile.exists()) {
-                        throw new BuildException("Source file does not exist!", getLocation());
+                    Reader reader;
+                    if (src instanceof FileResource) {
+                        File file = ((FileResource) src).getFile();
+                        createClasspath().add(new Path(getProject(), file.getParentFile().getCanonicalPath()));
+                        if (encoding != null && !encoding.isEmpty()) {
+                            reader = new LineNumberReader(new InputStreamReader(new FileInputStream(file), encoding));
+                        } else {
+                            reader = new CharsetToolkit(file).getReader();
+                        }
+                    } else {
+                        if (encoding != null && !encoding.isEmpty()) {
+                            reader = new InputStreamReader(new BufferedInputStream(src.getInputStream()), encoding);
+                        } else {
+                            reader = new InputStreamReader(new BufferedInputStream(src.getInputStream()), Charset.defaultCharset());
+                        }
+                    }
+                    try {
+                        final long len = src.getSize();
+                        log.debug("resource size = " + (len != Resource.UNKNOWN_SIZE ? String.valueOf(len) : "unknown"));
+                        if (len == 0) {
+                            log.info("Ignoring empty resource");
+                            command = null;
+                        } else {
+                            try (ChainReaderHelper.ChainReader chainReader = new ChainReaderHelper(getProject(), reader, filterChains).with(crh -> {
+                                if (len != Resource.UNKNOWN_SIZE && len <= Integer.MAX_VALUE) {
+                                    crh.setBufferSize((int) len);
+                                }
+                            }).getAssembledReader()) {
+                                command = chainReader.readFully();
+                            }
+                        }
+                    } catch (final IOException ioe) {
+                        throw new BuildException("Unable to load resource: ", ioe, getLocation());
+                    }
+                } else {
+                    if (src != null) {
+                        log.info("Ignoring supplied resource as direct script text found");
                     }
-                    createClasspath().add(new Path(getProject(), srcFile.getParentFile().getCanonicalPath()));
-                    command = getText(new CharsetToolkit(srcFile).getReader());
                 }
 
-                execGroovy(command, out);
+                if (command != null) {
+                    execGroovy(command, out);
+                }
 
             } finally {
                 if (out != null && out != System.out) {
@@ -351,20 +428,7 @@ public class Groovy extends Java {
             throw new BuildException(e, getLocation());
         }
 
-        log.verbose("statements executed successfully");
-    }
-
-    private static String getText(BufferedReader reader) throws IOException {
-        StringBuilder answer = new StringBuilder();
-        // reading the content of the file within a char buffer allow to keep the correct line endings
-        char[] charBuffer = new char[4096];
-        int nbCharRead = 0;
-        while ((nbCharRead = reader.read(charBuffer)) != -1) {
-            // appends buffer
-            answer.append(charBuffer, 0, nbCharRead);
-        }
-        reader.close();
-        return answer.toString();
+        log.verbose("Statements executed successfully");
     }
 
     public Commandline.Argument createArg() {
@@ -372,6 +436,25 @@ public class Groovy extends Java {
     }
 
     /**
+     * Add the FilterChain element.
+     * @param filter the filter to add
+     */
+    public final void addFilterChain(FilterChain filter) {
+        filterChains.add(filter);
+    }
+
+    /**
+     * Set the source resource.
+     * @param a the resource to load as a single element Resource collection.
+     */
+    public void addConfigured(ResourceCollection a) {
+        if (a.size() != 1) {
+            throw new BuildException("Only single argument resource collections are supported");
+        }
+        src = a.iterator().next();
+    }
+
+    /**
      * Read in lines and execute them.
      *
      * @param reader the reader from which to get the groovy source to exec
@@ -630,8 +713,9 @@ public class Groovy extends Java {
      * @return the name to use when compiling the script
      */
     private String computeScriptName() {
-        if (srcFile != null) {
-            return srcFile.getAbsolutePath();
+        if (src instanceof FileResource) {
+            FileResource fr = (FileResource) src;
+            return fr.getFile().getAbsolutePath();
         } else {
             String name = PREFIX;
             if (getLocation().getFileName().length() > 0)
@@ -663,8 +747,8 @@ public class Groovy extends Java {
      */
     protected void printResults(PrintStream out) {
         log.debug("printResults()");
-        StringBuilder line = new StringBuilder();
-        out.println(line);
+//        StringBuilder line = new StringBuilder();
+//        out.println(line);
         out.println();
     }
 
diff --git a/subprojects/groovy-ant/src/spec/doc/groovy-ant-task.adoc b/subprojects/groovy-ant/src/spec/doc/groovy-ant-task.adoc
index 9dfcd16..0867dfb 100644
--- a/subprojects/groovy-ant/src/spec/doc/groovy-ant-task.adoc
+++ b/subprojects/groovy-ant/src/spec/doc/groovy-ant-task.adoc
@@ -22,7 +22,7 @@
 = The <groovy> Ant Task
 
 Executes a series of Groovy statements from http://ant.apache.org/[Apache Ant].
-Statements can either be read in from a text file using the `src` attribute or from between the enclosing Groovy tags.
+Statements can either be read in from a resource or as direct text between the enclosing Groovy tags.
 
 == Required taskdef
 
@@ -38,22 +38,62 @@ the `groovy` task being invoked.
          classpathref="my.classpath"/>
 ----
 
-Now use the task like this:
+You can simply place statements between the `groovy` tags like this:
 
 [source,xml]
 ----
-<groovy src="..." otherAttributes="...">
+<groovy>
+...
+</groovy>
+----
+
+Or you can supply the Groovy source script as a resource. You can specify the pathname using the `src` attribute like this:
+
+[source,xml]
+----
+<groovy src="/some/path/MyGroovyScript.groovy" otherAttributes="...">
 ----
 
-Or this:
+Or as a nested `fileset` like this (though the fileset definition is expected to select just one file):
 
 [source,xml]
 ----
 <groovy>
-...
+    <fileset file="MyGroovyScript.groovy"/>
+</groovy>
+----
+
+Or as a nested single element https://ant.apache.org/manual/Types/resources.html#collection[resource collection] which could look like any of these:
+
+[source,xml]
+----
+<groovy>
+    <file file="MyGroovyScript.groovy"/>
+</groovy>
+
+<groovy>
+    <url url="https://some.domain/some/path/to/MyGroovyScript.groovy"/>
+</groovy>
+
+<groovy>
+    <javaconstant name="some.packagename.SomeClass.MY_CODE_FRAGMENT"/>
 </groovy>
 ----
 
+You may also supply a https://ant.apache.org/manual/Types/filterchain.html[filter chain] like this:
+
+[source,xml]
+----
+<groovy>
+    <fileset file="MyGroovyScript.groovy"/>
+    <!-- take 5 lines after skipping 18 lines, just as an example -->
+    <filterchain>
+        <headfilter lines="5" skip="18"/>
+    </filterchain>
+</groovy>
+----
+
+
 You might need to use the _contextClassLoader_ attribute (see below) if any of your modules load services via the classpath, e.g. `groovy-json`.
 
 == <groovy> attributes
diff --git a/subprojects/groovy-ant/src/test-resources/org/codehaus/groovy/ant/GroovyTest.xml b/subprojects/groovy-ant/src/test-resources/org/codehaus/groovy/ant/GroovyTest.xml
index 1efbb19..75b098d 100644
--- a/subprojects/groovy-ant/src/test-resources/org/codehaus/groovy/ant/GroovyTest.xml
+++ b/subprojects/groovy-ant/src/test-resources/org/codehaus/groovy/ant/GroovyTest.xml
@@ -39,6 +39,34 @@
         <groovy src="GroovyTest1.groovy"/>
     </target>
 
+    <target name="groovyCodeInExternalFileset" depends="defineTask">
+        <groovy>
+            <fileset file="GroovyTest1.groovy"/>
+            <!-- skip over copyright header, just as an example -->
+            <filterchain>
+                <headfilter skip="18"/>
+            </filterchain>
+        </groovy>
+    </target>
+
+    <target name="groovyCodeInExternalFileResource" depends="defineTask">
+        <groovy>
+            <file file="GroovyTest1.groovy"/>
+        </groovy>
+    </target>
+
+    <target name="groovyCodeInExternalJavaConstantResource" depends="defineTask">
+        <groovy>
+            <javaconstant name="org.codehaus.groovy.ant.GroovyTest.CODE_FRAGMENT"/>
+        </groovy>
+    </target>
+
+    <target name="groovyCodeInExternalURLResource" depends="defineTask">
+        <groovy>
+            <url url="https://raw.githubusercontent.com/apache/groovy/master/subprojects/groovy-ant/src/test-resources/org/codehaus/groovy/ant/GroovyTest1.groovy"/>
+        </groovy>
+    </target>
+
     <target name="groovyCodeInExternalFileWithOtherClass" depends="defineTask">
         <groovy src="GroovyTest2.groovy"/>
     </target>
@@ -100,6 +128,10 @@
         <groovy src="GroovyTest_errorMessage.groovy"/>
     </target>
 
+    <target name="groovyErrorMsg_NonExistingFile" depends="defineTask">
+        <groovy src="Does_not_exist.groovy"/>
+    </target>
+
     <target name="defineTask">
         <taskdef name="groovy" classname="org.codehaus.groovy.ant.Groovy"/>
     </target>
diff --git a/subprojects/groovy-ant/src/test/groovy/org/codehaus/groovy/ant/GroovyTest.java b/subprojects/groovy-ant/src/test/groovy/org/codehaus/groovy/ant/GroovyTest.java
index 8f9811f..e232373 100644
--- a/subprojects/groovy-ant/src/test/groovy/org/codehaus/groovy/ant/GroovyTest.java
+++ b/subprojects/groovy-ant/src/test/groovy/org/codehaus/groovy/ant/GroovyTest.java
@@ -40,6 +40,7 @@ import java.util.regex.Pattern;
  */
 public class GroovyTest extends GroovyTestCase {
     public static String FLAG = null;
+    public static final String CODE_FRAGMENT = "org.codehaus.groovy.ant.GroovyTest.FLAG = \"from Java constant resource\"";
     private final File antFile = new File("src/test-resources/org/codehaus/groovy/ant/GroovyTest.xml");
     private Project project;
 
@@ -51,6 +52,10 @@ public class GroovyTest extends GroovyTestCase {
         TestSuite suite = new TestSuite();
         suite.addTest(new GroovyTest("testGroovyCodeWithinTag"));
         suite.addTest(new GroovyTest("testGroovyCodeExternalFile"));
+        suite.addTest(new GroovyTest("testGroovyCodeExternalFileset"));
+        suite.addTest(new GroovyTest("testGroovyCodeExternalFileResource"));
+        suite.addTest(new GroovyTest("testGroovyCodeExternalURLResource"));
+        suite.addTest(new GroovyTest("testGroovyCodeExternalJavaConstantResource"));
         suite.addTest(new GroovyTest("testGroovyCodeInExternalFileWithOtherClass"));
         suite.addTest(new GroovyTest("testPropertiesWithoutFork"));
         suite.addTest(new GroovyTest("testClasspath_missing"));
@@ -59,6 +64,7 @@ public class GroovyTest extends GroovyTestCase {
         suite.addTest(new GroovyTest("testClasspath_nestedclasspath"));
         suite.addTest(new GroovyTest("testGroovyArgUsage"));
         suite.addTest(new GroovyTest("testFileNameInStackTrace"));
+        suite.addTest(new GroovyTest("testNonExistingFile"));
         return suite;
     }
 
@@ -86,6 +92,30 @@ public class GroovyTest extends GroovyTestCase {
         assertEquals("from groovy file called from ant", FLAG);
     }
 
+    public void testGroovyCodeExternalFileset() {
+        assertNull(FLAG);
+        project.executeTarget("groovyCodeInExternalFileset");
+        assertEquals("from groovy file called from ant", FLAG);
+    }
+
+    public void testGroovyCodeExternalFileResource() {
+        assertNull(FLAG);
+        project.executeTarget("groovyCodeInExternalFileResource");
+        assertEquals("from groovy file called from ant", FLAG);
+    }
+
+    public void testGroovyCodeExternalURLResource() {
+        assertNull(FLAG);
+        project.executeTarget("groovyCodeInExternalURLResource");
+        assertEquals("from groovy file called from ant", FLAG);
+    }
+
+    public void testGroovyCodeExternalJavaConstantResource() {
+        assertNull(FLAG);
+        project.executeTarget("groovyCodeInExternalJavaConstantResource");
+        assertEquals("from Java constant resource", FLAG);
+    }
+
     public void testPropertiesWithoutFork() {
         assertNull(FLAG);
         project.executeTarget("groovyAntPropertyWithoutFork");
@@ -131,6 +161,16 @@ public class GroovyTest extends GroovyTestCase {
         assertEquals("from groovytest3.GroovyTest3Class.doSomethingWithArgs() 1 2 3", FLAG);
     }
 
+    public void testNonExistingFile() {
+        try {
+            project.executeTarget("groovyErrorMsg_NonExistingFile");
+            fail();
+        }
+        catch (final BuildException e) {
+            assertTrue(e.getMessage().contains("Source resource does not exist!"));
+        }
+    }
+
     /**
      * Test that helpful "file name" appears in the stack trace and not just "Script1" 
      */


[groovy] 02/02: GROOVY-9440: Missing line number information in stack trace (provide fallback)

Posted by pa...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

paulk pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/groovy.git

commit a01d7fbdf42029003cdbcdd0804c4d1b49123c3f
Author: Paul King <pa...@asert.com.au>
AuthorDate: Thu Mar 26 12:53:04 2020 +1000

    GROOVY-9440: Missing line number information in stack trace (provide fallback)
---
 src/main/java/org/codehaus/groovy/classgen/ReturnAdder.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/main/java/org/codehaus/groovy/classgen/ReturnAdder.java b/src/main/java/org/codehaus/groovy/classgen/ReturnAdder.java
index f8f3bf4..b206c16 100644
--- a/src/main/java/org/codehaus/groovy/classgen/ReturnAdder.java
+++ b/src/main/java/org/codehaus/groovy/classgen/ReturnAdder.java
@@ -114,7 +114,7 @@ public class ReturnAdder {
             Expression expression = ((ExpressionStatement) statement).getExpression();
             ReturnStatement returnStatement = new ReturnStatement(expression);
             returnStatement.copyStatementLabels(statement);
-            returnStatement.setSourcePosition(statement);
+            returnStatement.setSourcePosition(statement.getLineNumber() < 0 ? expression : statement);
             listener.returnStatementAdded(returnStatement);
             return returnStatement;
         }