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

jamesfredley pushed a commit to branch 7.0.x
in repository https://gitbox.apache.org/repos/asf/grails-core.git


The following commit(s) were added to refs/heads/7.0.x by this push:
     new ba70c5fb1a Adopt AntBuilder groovydoc with javaVersion support (#15420)
ba70c5fb1a is described below

commit ba70c5fb1a1a349c15ae3a269c4d2276c32eda53
Author: James Fredley <[email protected]>
AuthorDate: Wed Feb 25 20:18:53 2026 -0500

    Adopt AntBuilder groovydoc with javaVersion support (#15420)
    
    * Adopt AntBuilder groovydoc with javaVersion support
    
    Replace Gradle's built-in Groovydoc task execution with AntBuilder to
    support the javaVersion parameter introduced in Groovy 4.0.27
    (GROOVY-11668). This is needed because Gradle's Groovydoc task does not
    expose javaVersion (gradle/gradle#33659 is not merged), causing Java 17+
    source parsing failures.
    
    Changes across all groovydoc configurations:
    - gradle/docs-dependencies.gradle: central config for ~90 modules and
      both aggregate tasks (aggregateGroovydoc, aggregateDataMappingGroovydoc)
    - gradle/docs-config.gradle: per-module source directory setup
    - grails-doc/build.gradle: aggregate task source directories
    - grails-data-docs/stage/build.gradle: data mapping aggregate source dirs
    - grails-gradle/gradle/docs-config.gradle: independent AntBuilder setup
    - grails-data-hibernate5/docs/build.gradle: added groovy-ant dependency
      and AntBuilder execution
    - grails-data-mongodb/docs/build.gradle: added groovy-ant dependency
      and AntBuilder execution
    - grails-forge/gradle/doc-config.gradle: AntBuilder without javaVersion
      (forge uses Groovy 3.0.25 which predates the feature)
    
    Closes #15385
    
    Assisted-by: Claude Code <[email protected]>
    
    * Centralize groovydoc configuration into GrailsGroovydocPlugin convention 
plugin
    
    Move duplicated AntBuilder groovydoc execution, Matomo footer, documentation
    configuration registration, and task defaults into a shared convention 
plugin
    in build-logic. This eliminates ~490 lines of duplicated configuration 
across
    8 build scripts while maintaining identical behavior.
    
    The plugin provides:
    - Documentation configuration registration with standard attributes
    - Common Groovydoc task defaults (author, timestamps, scripts)
    - AntBuilder-based execution with javaVersion support (Groovy 4.0.27+)
    - Matomo analytics footer
    - Source directory resolution from ext.groovydocSourceDirs or source sets
    - External documentation link support via ext.groovydocLinks
    - GrailsGroovydocExtension for per-project javaVersion control
    
    Build scripts retain project-specific configuration: dependencies, titles,
    source directories for aggregate tasks, and dynamic link resolution.
    
    Assisted-by: Claude Code <[email protected]>
    
    * Split groovydoc plugin into generic base and Grails layer
    
    Separate GrailsGroovydocPlugin into a generic GroovydocEnhancerPlugin
    (with GroovydocEnhancerExtension) and a thin GrailsGroovydocPlugin that
    applies the base plugin and sets the Matomo footer. This makes the core
    AntBuilder groovydoc logic publishable and reusable by anyone, while
    keeping Grails-specific customizations in their own layer.
    
    The base plugin supports a useAntBuilder flag so projects can easily
    switch back to Gradle's built-in Groovydoc task if Gradle merges their
    javaVersion support (gradle/gradle#33659).
    
    Also fix a pre-existing bug in resolveProjectVersion() in
    docs-dependencies.gradle where the function never returned the resolved
    version string, causing all external groovydoc links (geb,
    testcontainers, spring, spring-boot) to be silently omitted.
    
    Assisted-by: Claude Code <[email protected]>
    
    * style: simplify groovydoc plugin
    
    * fix: use lazy provider for javaVersion convention
    
    Wrap the javaVersion convention in project.provider so the property
    is resolved at execution time rather than configuration time.
    
    Assisted-by: Claude Code <[email protected]>
    
    * fix: use gdoc.groovyClasspath instead of redundant configuration lookup
    
    Use the task's groovyClasspath property directly instead of looking up
    the 'documentation' configuration a second time, since it was already
    assigned in configureGroovydocDefaults.
    
    Assisted-by: OpenCode <[email protected]>
    
    * fix: fail groovydoc task instead of silently skipping when sources or 
classpath are missing
    
    Maven Central requires a groovydoc jar for every published module. Silently 
skipping
    when source directories or groovyClasspath are empty masks configuration 
errors that
    would prevent a valid release. Throw GradleException to surface these 
issues early.
    
    Assisted-by: OpenCode <[email protected]>
    
    * fix: require javaVersion property instead of defaulting to 17
    
    Remove the silent '17' fallback so a missing javaVersion property in
    gradle.properties fails the build with a clear error message rather
    than producing potentially incorrect groovydoc output.
    
    Assisted-by: Claude Code <[email protected]>
    
    ---------
    
    Co-authored-by: Mattias Reichel <[email protected]>
---
 build-logic/plugins/build.gradle                   |   8 +
 .../grails/buildsrc/GrailsGroovydocPlugin.groovy   |  40 ++---
 .../buildsrc/GroovydocEnhancerExtension.groovy     | 108 +++++++++++++
 .../grails/buildsrc/GroovydocEnhancerPlugin.groovy | 180 +++++++++++++++++++++
 gradle/docs-dependencies.gradle                    |  61 ++-----
 grails-data-docs/stage/build.gradle                |  27 +---
 grails-data-hibernate5/docs/build.gradle           |  43 ++---
 grails-data-mongodb/docs/build.gradle              |  43 ++---
 grails-doc/build.gradle                            |  21 +--
 grails-forge/gradle/doc-config.gradle              |  45 ++----
 grails-gradle/gradle/docs-config.gradle            |  35 +---
 11 files changed, 375 insertions(+), 236 deletions(-)

diff --git a/build-logic/plugins/build.gradle b/build-logic/plugins/build.gradle
index e85254e152..90240300d6 100644
--- a/build-logic/plugins/build.gradle
+++ b/build-logic/plugins/build.gradle
@@ -62,6 +62,14 @@ gradlePlugin {
             id = 'org.apache.grails.gradle.grails-code-style'
             implementationClass = 
'org.apache.grails.buildsrc.GrailsCodeStylePlugin'
         }
+        register('groovydocEnhancer') {
+            id = 'org.apache.grails.buildsrc.groovydoc-enhancer'
+            implementationClass = 
'org.apache.grails.buildsrc.GroovydocEnhancerPlugin'
+        }
+        register('grailsGroovydoc') {
+            id = 'org.apache.grails.buildsrc.groovydoc'
+            implementationClass = 
'org.apache.grails.buildsrc.GrailsGroovydocPlugin'
+        }
         register('grailsRepoSettings') {
             id = 'org.apache.grails.buildsrc.repo'
             implementationClass = 
'org.apache.grails.buildsrc.GrailsRepoSettingsPlugin'
diff --git a/grails-forge/gradle/doc-config.gradle 
b/build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/GrailsGroovydocPlugin.groovy
similarity index 59%
copy from grails-forge/gradle/doc-config.gradle
copy to 
build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/GrailsGroovydocPlugin.groovy
index d7b0eaf7fb..b10a77a93c 100644
--- a/grails-forge/gradle/doc-config.gradle
+++ 
b/build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/GrailsGroovydocPlugin.groovy
@@ -16,27 +16,18 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
+package org.apache.grails.buildsrc
 
-configurations.register('documentation') {
-    canBeConsumed = false
-    canBeResolved = true
-    attributes {
-        attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category, 
Category.LIBRARY))
-        attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling, 
Bundling.EXTERNAL))
-        attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, 
Usage.JAVA_RUNTIME))
-    }
-}
+import groovy.transform.CompileStatic
 
-dependencies {
-    documentation "org.codehaus.groovy:groovy-templates:$groovyVersion"
-    documentation "org.codehaus.groovy:groovy-dateutil:$groovyVersion"
-}
+import org.gradle.api.Plugin
+import org.gradle.api.Project
 
-tasks.withType(Groovydoc).configureEach {
-    classpath += project.configurations.documentation
-    windowTitle = "${project.findProperty('pomArtifactId') ?: project.name} - 
$projectVersion"
-    docTitle = "${project.findProperty('pomArtifactId') ?: project.name} - 
$projectVersion"
-    footer = '''<!-- Matomo -->
+@CompileStatic
+class GrailsGroovydocPlugin implements Plugin<Project> {
+
+    static final String MATOMO_FOOTER = '''\
+<!-- Matomo -->
 <script>
     var _paq = window._paq = window._paq || [];
     /* tracker methods like "setCustomDimension" should be called before 
"trackPageView" */
@@ -53,10 +44,11 @@ tasks.withType(Groovydoc).configureEach {
     })();
 </script>
 <!-- End Matomo Code -->'''
-    access = GroovydocAccess.PROTECTED
-    includeAuthor = false
-    includeMainForScripts = false
-    processScripts = false
-    noTimestamp = true
-    noVersionStamp = false
+
+    @Override
+    void apply(Project project) {
+        project.pluginManager.apply(GroovydocEnhancerPlugin)
+        project.extensions.getByType(GroovydocEnhancerExtension)
+                .footer.set(MATOMO_FOOTER)
+    }
 }
diff --git 
a/build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/GroovydocEnhancerExtension.groovy
 
b/build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/GroovydocEnhancerExtension.groovy
new file mode 100644
index 0000000000..15d61ca98d
--- /dev/null
+++ 
b/build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/GroovydocEnhancerExtension.groovy
@@ -0,0 +1,108 @@
+/*
+ *  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
+ *
+ *    https://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.
+ */
+package org.apache.grails.buildsrc
+
+import javax.inject.Inject
+
+import groovy.transform.CompileStatic
+
+import org.gradle.api.Project
+import org.gradle.api.model.ObjectFactory
+import org.gradle.api.provider.Property
+
+/**
+ * Extension for configuring the Groovydoc Enhancer convention plugin.
+ *
+ * <p>This plugin replaces Gradle's built-in Groovydoc task execution with
+ * a direct AntBuilder invocation of the Groovy {@code 
org.codehaus.groovy.ant.Groovydoc}
+ * Ant task. This enables the {@code javaVersion} parameter (added in Groovy 
4.0.27,
+ * GROOVY-11668) which controls the JavaParser language level used when parsing
+ * Java source files.</p>
+ *
+ * <p>When Gradle natively supports the {@code javaVersion} property
+ * (see <a 
href="https://github.com/gradle/gradle/issues/33659";>gradle#33659</a>),
+ * set {@link #useAntBuilder} to {@code false} to revert to Gradle's built-in
+ * Groovydoc task execution while retaining all other configuration (footer,
+ * defaults, etc.).</p>
+ *
+ * @since 7.0.8
+ */
+@CompileStatic
+class GroovydocEnhancerExtension {
+
+    /**
+     * The Java language level string passed to the groovydoc Ant task's
+     * {@code javaVersion} parameter (e.g. {@code "JAVA_17"}, {@code 
"JAVA_21"}).
+     *
+     * <p>Derived from the project's {@code javaVersion} property
+     * (e.g. {@code "JAVA_17"}). The property must be defined in
+     * {@code gradle.properties}; a missing value will cause a build 
failure.</p>
+     */
+    final Property<String> javaVersion
+
+    /**
+     * Whether to pass the {@code javaVersion} parameter to the groovydoc
+     * Ant task. Set to {@code false} for projects using Groovy versions
+     * older than 4.0.27 (which do not support the parameter).
+     *
+     * <p>Defaults to {@code true}.</p>
+     */
+    final Property<Boolean> javaVersionEnabled
+
+    /**
+     * Whether to replace Gradle's built-in Groovydoc task execution with
+     * AntBuilder invocation. When {@code true} (default), the plugin clears
+     * the task's actions and replaces them with a {@code doLast} that uses
+     * AntBuilder. When {@code false}, the plugin only applies property
+     * defaults (footer, etc.) and lets Gradle's built-in task run normally.
+     *
+     * <p>Set to {@code false} when Gradle adds native {@code javaVersion}
+     * support (gradle/gradle#33659).</p>
+     *
+     * <p>Defaults to {@code true}.</p>
+     */
+    final Property<Boolean> useAntBuilder
+
+    /**
+     * HTML footer appended to every generated groovydoc page. Useful for
+     * analytics scripts, copyright notices, or custom branding.
+     *
+     * <p>Defaults to an empty string (no footer).</p>
+     */
+    final Property<String> footer
+
+    @Inject
+    GroovydocEnhancerExtension(ObjectFactory objects, Project project) {
+        javaVersion = objects.property(String).convention(
+                project.provider {
+                    def ver = GradleUtils.findProperty(project, 'javaVersion')
+                    if (ver == null) {
+                        throw new IllegalStateException(
+                                "Required project property 'javaVersion' is 
not set. " +
+                                "Define it in gradle.properties (e.g. 
javaVersion=17)."
+                        )
+                    }
+                    "JAVA_${ver}" as String
+                }
+        )
+        javaVersionEnabled = objects.property(Boolean).convention(true)
+        useAntBuilder = objects.property(Boolean).convention(true)
+        footer = objects.property(String).convention('')
+    }
+}
diff --git 
a/build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/GroovydocEnhancerPlugin.groovy
 
b/build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/GroovydocEnhancerPlugin.groovy
new file mode 100644
index 0000000000..e667c5f8a0
--- /dev/null
+++ 
b/build-logic/plugins/src/main/groovy/org/apache/grails/buildsrc/GroovydocEnhancerPlugin.groovy
@@ -0,0 +1,180 @@
+/*
+ *  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
+ *
+ *    https://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.
+ */
+package org.apache.grails.buildsrc
+
+import groovy.transform.CompileDynamic
+import groovy.transform.CompileStatic
+
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.api.attributes.Bundling
+import org.gradle.api.attributes.Category
+import org.gradle.api.attributes.Usage
+import org.gradle.api.provider.Provider
+import org.gradle.api.tasks.SourceSetContainer
+import org.gradle.api.tasks.javadoc.Groovydoc
+
+@CompileStatic
+class GroovydocEnhancerPlugin implements Plugin<Project> {
+
+    @Override
+    void apply(Project project) {
+        GroovydocEnhancerExtension extension = project.extensions.create(
+                'groovydocEnhancer',
+                GroovydocEnhancerExtension,
+                project
+        )
+        registerDocumentationConfiguration(project)
+        configureGroovydocDefaults(project, extension)
+        configureAntBuilderExecution(project, extension)
+    }
+
+    private static void registerDocumentationConfiguration(Project project) {
+        if (project.configurations.names.contains('documentation')) {
+            return
+        }
+        project.configurations.register('documentation') {
+            it.canBeConsumed = false
+            it.canBeResolved = true
+            it.attributes {
+                it.attribute(Category.CATEGORY_ATTRIBUTE, 
project.objects.named(Category, Category.LIBRARY))
+                it.attribute(Bundling.BUNDLING_ATTRIBUTE, 
project.objects.named(Bundling, Bundling.EXTERNAL))
+                it.attribute(Usage.USAGE_ATTRIBUTE, 
project.objects.named(Usage, Usage.JAVA_RUNTIME))
+            }
+        }
+    }
+
+    @CompileDynamic
+    private static void configureGroovydocDefaults(Project project, 
GroovydocEnhancerExtension extension) {
+        project.tasks.withType(Groovydoc).configureEach {
+            it.includeAuthor.set(false)
+            it.includeMainForScripts.set(false)
+            it.processScripts.set(false)
+            it.noTimestamp = true
+            it.noVersionStamp = false
+            def footerValue = extension.footer.getOrElse('')
+            if (footerValue) {
+                it.footer = footerValue
+            }
+            if (project.configurations.names.contains('documentation')) {
+                it.groovyClasspath = 
project.configurations.getByName('documentation')
+            }
+        }
+    }
+
+    @CompileDynamic
+    private static void configureAntBuilderExecution(Project project, 
GroovydocEnhancerExtension extension) {
+        project.tasks.withType(Groovydoc).configureEach { gdoc ->
+            if (!extension.useAntBuilder.get()) {
+                return
+            }
+
+            gdoc.actions.clear()
+            gdoc.doLast {
+                def destDir = gdoc.destinationDir.tap { it.mkdirs() }
+                def sourceDirs = resolveSourceDirectories(gdoc, project)
+                if (sourceDirs.isEmpty()) {
+                    throw new org.gradle.api.GradleException(
+                            "groovydoc task '${gdoc.name}': no source 
directories found. " +
+                            'Every published module must produce a groovydoc 
jar for Maven Central.'
+                    )
+                }
+
+                def classpath = gdoc.groovyClasspath
+                if (!classpath || classpath.empty) {
+                    throw new org.gradle.api.GradleException(
+                            "groovydoc task '${gdoc.name}': groovyClasspath is 
empty. " +
+                            'Every published module must produce a groovydoc 
jar for Maven Central.'
+                    )
+                }
+
+                project.ant.taskdef(
+                        name: 'groovydoc',
+                        classname: 'org.codehaus.groovy.ant.Groovydoc',
+                        classpath: classpath.asPath
+                )
+
+                def links = resolveLinks(gdoc)
+                def sourcepath = sourceDirs
+                        .collect { it.absolutePath }
+                        .join(File.pathSeparator)
+
+                def antArgs = [
+                        destdir: destDir.absolutePath,
+                        sourcepath: sourcepath,
+                        packagenames: '**.*',
+                        windowtitle: gdoc.windowTitle ?: '',
+                        doctitle: gdoc.docTitle ?: '',
+                        footer: gdoc.footer ?: '',
+                        access: 
resolveGroovydocProperty(gdoc.access)?.name()?.toLowerCase() ?: 'protected',
+                        author: resolveGroovydocProperty(gdoc.includeAuthor) 
as String,
+                        noTimestamp: 
resolveGroovydocProperty(gdoc.noTimestamp) as String,
+                        noVersionStamp: 
resolveGroovydocProperty(gdoc.noVersionStamp) as String,
+                        processScripts: 
resolveGroovydocProperty(gdoc.processScripts) as String,
+                        includeMainForScripts: 
resolveGroovydocProperty(gdoc.includeMainForScripts) as String
+                ]
+
+                if (extension.javaVersionEnabled.get()) {
+                    antArgs.put('javaVersion', extension.javaVersion.get())
+                }
+
+                project.ant.groovydoc(antArgs) {
+                    for (var l in links) {
+                        link(packages: l.packages, href: l.href)
+                    }
+                }
+            }
+        }
+    }
+
+    @CompileDynamic
+    private static List<File> resolveSourceDirectories(Groovydoc gdoc, Project 
project) {
+        if (gdoc.ext.has('groovydocSourceDirs') && 
gdoc.ext.groovydocSourceDirs) {
+            return (gdoc.ext.groovydocSourceDirs as List<File>)
+                    .findAll { it.exists() }
+                    .unique()
+        }
+
+        List<File> sourceDirs = []
+        def sourceSets = project.extensions.findByType(SourceSetContainer)
+        if (sourceSets) {
+            def mainSS = sourceSets.findByName('main')
+            if (mainSS) {
+                sourceDirs.addAll(mainSS.groovy.srcDirs.findAll { it.exists() 
})
+                sourceDirs.addAll(mainSS.java.srcDirs.findAll { it.exists() })
+            }
+        }
+        sourceDirs.unique()
+    }
+
+    @CompileDynamic
+    private static List<Map<String, String>> resolveLinks(Groovydoc gdoc) {
+        if (gdoc.ext.has('groovydocLinks')) {
+            return gdoc.ext.groovydocLinks as List<Map<String, String>>
+        }
+        []
+    }
+
+    static Object resolveGroovydocProperty(Object value) {
+        if (value instanceof Provider) {
+            return ((Provider) value).getOrNull()
+        }
+        value
+    }
+}
diff --git a/gradle/docs-dependencies.gradle b/gradle/docs-dependencies.gradle
index df4244f39c..ec9c6da7e1 100644
--- a/gradle/docs-dependencies.gradle
+++ b/gradle/docs-dependencies.gradle
@@ -16,15 +16,7 @@
  *  specific language governing permissions and limitations
  *  under the License.
  */
-configurations.register('documentation') {
-    canBeConsumed = false
-    canBeResolved = true
-    attributes {
-        attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category, 
Category.LIBRARY))
-        attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling, 
Bundling.EXTERNAL))
-        attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, 
Usage.JAVA_RUNTIME))
-    }
-}
+apply plugin: 'org.apache.grails.buildsrc.groovydoc'
 
 dependencies {
     add('documentation', platform(project(':grails-bom')))
@@ -48,56 +40,35 @@ String resolveProjectVersion(String artifact) {
     if (!version) {
         return null
     }
+    version
 }
 
 tasks.withType(Groovydoc).configureEach { Groovydoc gdoc ->
     gdoc.exclude('META-INF/**', '*yml', '*properties', '*xml', 
'**/Application.groovy', '**/Bootstrap.groovy', '**/resources.groovy')
-    gdoc.groovyClasspath = configurations.documentation
     gdoc.windowTitle = "${project.findProperty('pomArtifactId') ?: 
project.name} - $projectVersion"
     gdoc.docTitle = "${project.findProperty('pomArtifactId') ?: project.name} 
- $projectVersion"
-    gdoc.access = GroovydocAccess.PROTECTED
-    gdoc.includeAuthor = false
-    gdoc.includeMainForScripts = false
-    gdoc.processScripts = false
-    gdoc.noTimestamp = true
-    gdoc.noVersionStamp = false
-    gdoc.footer = '''<!-- Matomo -->
-<script>
-    var _paq = window._paq = window._paq || [];
-    /* tracker methods like "setCustomDimension" should be called before 
"trackPageView" */
-    _paq.push(["setDoNotTrack", true]);
-    _paq.push(["disableCookies"]);
-    _paq.push(['trackPageView']);
-    _paq.push(['enableLinkTracking']);
-    (function() {
-        var u="https://analytics.apache.org/";;
-        _paq.push(['setTrackerUrl', u+'matomo.php']);
-        _paq.push(['setSiteId', '79']);
-        var d=document, g=d.createElement('script'), 
s=d.getElementsByTagName('script')[0];
-        g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
-    })();
-</script>
-<!-- End Matomo Code -->'''
 
-    doFirst {
+    gdoc.doFirst {
+        List<Map<String, String>> links = []
         def gebVersion = resolveProjectVersion('geb-spock')
-        if(gebVersion) {
-            
gdoc.link("https://groovy.apache.org/geb/manual/${gebVersion}/api/";, 'geb.')
+        if (gebVersion) {
+            links << [packages: 'geb.', href: 
"https://groovy.apache.org/geb/manual/${gebVersion}/api/";]
         }
-
         def testContainersVersion = resolveProjectVersion('testcontainers')
-        if(testContainersVersion) {
-            
gdoc.link("https://javadoc.io/doc/org.testcontainers/testcontainers/${testContainersVersion}/";,
 'org.testcontainers.')
+        if (testContainersVersion) {
+            links << [packages: 'org.testcontainers.', href: 
"https://javadoc.io/doc/org.testcontainers/testcontainers/${testContainersVersion}/";]
         }
-
         def springVersion = resolveProjectVersion('spring-core')
-        if(springVersion) {
-            
gdoc.link("https://docs.spring.io/spring-framework/docs/${springVersion}/javadoc-api/";,
 'org.springframework.core.')
+        if (springVersion) {
+            links << [packages: 'org.springframework.core.', href: 
"https://docs.spring.io/spring-framework/docs/${springVersion}/javadoc-api/";]
         }
-
         def springBootVersion = resolveProjectVersion('spring-boot')
-        if(springBootVersion) {
-            
gdoc.link("https://docs.spring.io/spring-boot/docs/${springBootVersion}/api/";, 
'org.springframework.boot.')
+        if (springBootVersion) {
+            links << [packages: 'org.springframework.boot.', href: 
"https://docs.spring.io/spring-boot/docs/${springBootVersion}/api/";]
+        }
+        if (gdoc.ext.has('groovydocLinks')) {
+            links.addAll(gdoc.ext.groovydocLinks as List<Map<String, String>>)
         }
+        gdoc.ext.groovydocLinks = links
     }
 }
\ No newline at end of file
diff --git a/grails-data-docs/stage/build.gradle 
b/grails-data-docs/stage/build.gradle
index b5d71cc03a..5af7d88544 100644
--- a/grails-data-docs/stage/build.gradle
+++ b/grails-data-docs/stage/build.gradle
@@ -25,23 +25,6 @@ apply from: 
rootProject.layout.projectDirectory.file('gradle/docs-dependencies.g
 combinedGroovydoc.configure { Groovydoc task ->
     task.windowTitle = "Grails Data Mapping API - ${projectVersion}"
     task.docTitle = "Grails Data Mapping API - ${projectVersion}"
-    task.footer = '''<!-- Matomo -->
-<script>
-    var _paq = window._paq = window._paq || [];
-    /* tracker methods like "setCustomDimension" should be called before 
"trackPageView" */
-    _paq.push(["setDoNotTrack", true]);
-    _paq.push(["disableCookies"]);
-    _paq.push(['trackPageView']);
-    _paq.push(['enableLinkTracking']);
-    (function() {
-        var u="https://analytics.apache.org/";;
-        _paq.push(['setTrackerUrl', u+'matomo.php']);
-        _paq.push(['setSiteId', '79']);
-        var d=document, g=d.createElement('script'), 
s=d.getElementsByTagName('script')[0];
-        g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
-    })();
-</script>
-<!-- End Matomo Code -->'''
 
     Set<Project> docProjects = rootProject.subprojects.findAll {
         it.name in [
@@ -77,14 +60,16 @@ combinedGroovydoc.configure { Groovydoc task ->
             }
             .flatten()
 
-    task.source(sources.collect{ SourceSet it -> [it.allSource.srcDirs, 
it.allSource.srcDirs] }.flatten().findAll { File srcDir ->
-        if(!(srcDir.name in ['java', 'groovy'])) {
+    def allSourceDirs = sources.collect { SourceSet it -> 
[it.allSource.srcDirs, it.allSource.srcDirs] }.flatten().findAll { File srcDir 
->
+        if (!(srcDir.name in ['java', 'groovy'])) {
             return false
         }
 
         srcDir.exists()
-    }.unique())
-    task.classpath = files(sources.collect{ SourceSet it -> 
it.compileClasspath.filter(File.&isDirectory) }.flatten().unique())
+    }.unique()
+    task.source(allSourceDirs)
+    task.ext.groovydocSourceDirs = allSourceDirs
+    task.classpath = files(sources.collect { SourceSet it -> 
it.compileClasspath.filter(File.&isDirectory) }.flatten().unique())
     task.destinationDir = 
project.layout.buildDirectory.dir('data-api/api').get().asFile
 
     
task.inputs.files(task.source).withPropertyName("groovyDocSrc").withPathSensitivity(PathSensitivity.RELATIVE)
diff --git a/grails-data-hibernate5/docs/build.gradle 
b/grails-data-hibernate5/docs/build.gradle
index aed5772187..be9c04f90d 100644
--- a/grails-data-hibernate5/docs/build.gradle
+++ b/grails-data-hibernate5/docs/build.gradle
@@ -31,20 +31,18 @@ ext {
     coreProjects = ['grails-datastore-core', 'grails-datamapping-core']
 }
 
-configurations {
-    documentation {
-        attributes {
-            attribute(Bundling.BUNDLING_ATTRIBUTE, (Bundling) 
(objects.named(Bundling, 'external')))
-        }
-    }
-}
+apply plugin: 'org.apache.grails.buildsrc.groovydoc'
 
 dependencies {
     documentation platform(project(':grails-bom'))
     documentation 'com.github.javaparser:javaparser-core'
     documentation "info.picocli:picocli:$picocliVersion"
     documentation 'org.apache.groovy:groovy-dateutil'
+    documentation 'org.apache.groovy:groovy-ant'
+    documentation 'org.apache.groovy:groovy-groovydoc'
+    documentation 'org.apache.groovy:groovy-templates'
     documentation 'org.fusesource.jansi:jansi'
+    documentation 'jline:jline'
     documentation project(':grails-bootstrap')
     documentation project(':grails-core')
     documentation project(':grails-spring')
@@ -96,23 +94,6 @@ tasks.withType(Groovydoc).configureEach {
             .collect { ":${it.name}:groovydoc" })
 
     it.docTitle = "GORM for Hibernate 5 - $project.version"
-    it.footer = '''<!-- Matomo -->
-<script>
-    var _paq = window._paq = window._paq || [];
-    /* tracker methods like "setCustomDimension" should be called before 
"trackPageView" */
-    _paq.push(["setDoNotTrack", true]);
-    _paq.push(["disableCookies"]);
-    _paq.push(['trackPageView']);
-    _paq.push(['enableLinkTracking']);
-    (function() {
-        var u="https://analytics.apache.org/";;
-        _paq.push(['setTrackerUrl', u+'matomo.php']);
-        _paq.push(['setSiteId', '79']);
-        var d=document, g=d.createElement('script'), 
s=d.getElementsByTagName('script')[0];
-        g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
-    })();
-</script>
-<!-- End Matomo Code -->'''
 
     def sourceFiles = coreProjects.collect {
         rootProject.layout.projectDirectory.files("$it/src/main/groovy")
@@ -124,13 +105,15 @@ tasks.withType(Groovydoc).configureEach {
 
     it.source = sourceFiles
     it.destinationDir = 
layout.buildDirectory.dir('combined-api/api').get().asFile
-    it.access = GroovydocAccess.PROTECTED
-    it.processScripts = false
-    it.includeMainForScripts = false
-    it.includeAuthor = false
     it.classpath = configurations.documentation
-    it.groovyClasspath += configurations.documentation
-    it.noVersionStamp = false
+
+    List<File> groovydocSrcDirs = coreProjects.collect {
+        rootProject.layout.projectDirectory.dir("$it/src/main/groovy").asFile
+    }
+    rootProject.subprojects
+            .findAll { sp -> sp.findProperty('gormApiDocs') }
+            .each { sp -> groovydocSrcDirs << new File(sp.projectDir, 
'src/main/groovy') }
+    it.ext.groovydocSourceDirs = groovydocSrcDirs
 }
 
 tasks.register('docs', Sync).configure { Sync docTask ->
diff --git a/grails-data-mongodb/docs/build.gradle 
b/grails-data-mongodb/docs/build.gradle
index 89cfce4530..02de80eb95 100644
--- a/grails-data-mongodb/docs/build.gradle
+++ b/grails-data-mongodb/docs/build.gradle
@@ -31,13 +31,7 @@ ext {
     coreProjects = ['grails-datastore-core', 'grails-datamapping-core']
 }
 
-configurations {
-    documentation {
-        attributes {
-            attribute(Bundling.BUNDLING_ATTRIBUTE, (Bundling) 
(objects.named(Bundling, 'external')))
-        }
-    }
-}
+apply plugin: 'org.apache.grails.buildsrc.groovydoc'
 
 tasks.register('resolveMongodbVersion').configure { Task docTask ->
     docTask.group = 'documentation'
@@ -56,7 +50,10 @@ tasks.register('resolveMongodbVersion').configure { Task 
docTask ->
 dependencies {
     documentation platform(project(':grails-bom'))
     documentation 'org.fusesource.jansi:jansi'
+    documentation 'jline:jline'
     documentation 'org.apache.groovy:groovy'
+    documentation 'org.apache.groovy:groovy-ant'
+    documentation 'org.apache.groovy:groovy-groovydoc'
     documentation 'org.apache.groovy:groovy-templates'
     documentation 'org.apache.groovy:groovy-dateutil'
     documentation 'com.github.javaparser:javaparser-core'
@@ -105,23 +102,7 @@ tasks.withType(Groovydoc).configureEach { Groovydoc 
groovydoc ->
             .findAll { it.findProperty('gormApiDocs') }
             .collect { ":${it.name}:groovydoc" })
     groovydoc.docTitle = "GORM for MongoDB - $project.version"
-    groovydoc.footer = '''<!-- Matomo -->
-<script>
-    var _paq = window._paq = window._paq || [];
-    /* tracker methods like "setCustomDimension" should be called before 
"trackPageView" */
-    _paq.push(["setDoNotTrack", true]);
-    _paq.push(["disableCookies"]);
-    _paq.push(['trackPageView']);
-    _paq.push(['enableLinkTracking']);
-    (function() {
-        var u="https://analytics.apache.org/";;
-        _paq.push(['setTrackerUrl', u+'matomo.php']);
-        _paq.push(['setSiteId', '79']);
-        var d=document, g=d.createElement('script'), 
s=d.getElementsByTagName('script')[0];
-        g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
-    })();
-</script>
-<!-- End Matomo Code -->'''
+    groovydoc.includeAuthor = true
 
     def sourceFiles = coreProjects.collect {
         layout.projectDirectory.files("$it/src/main/groovy")
@@ -133,13 +114,15 @@ tasks.withType(Groovydoc).configureEach { Groovydoc 
groovydoc ->
 
     groovydoc.source = sourceFiles
     groovydoc.destinationDir = 
layout.buildDirectory.dir('combined-api/api').get().asFile
-    groovydoc.access = GroovydocAccess.PROTECTED
-    groovydoc.processScripts = false
-    groovydoc.includeMainForScripts = false
-    groovydoc.includeAuthor = true
     groovydoc.classpath = configurations.documentation
-    groovydoc.groovyClasspath += configurations.documentation
-    groovydoc.noVersionStamp = false
+
+    List<File> groovydocSrcDirs = coreProjects.collect {
+        layout.projectDirectory.dir("$it/src/main/groovy").asFile
+    }
+    rootProject.subprojects
+            .findAll { sp -> sp.findProperty('gormApiDocs') }
+            .each { sp -> groovydocSrcDirs << new File(sp.projectDir, 
'src/main/groovy') }
+    groovydoc.ext.groovydocSourceDirs = groovydocSrcDirs
 }
 
 tasks.register('docs', Sync).configure { Sync docTask ->
diff --git a/grails-doc/build.gradle b/grails-doc/build.gradle
index 1802c28395..4f7c1d9d87 100644
--- a/grails-doc/build.gradle
+++ b/grails-doc/build.gradle
@@ -63,23 +63,6 @@ apply from: 
rootProject.layout.projectDirectory.file('gradle/docs-dependencies.g
 combinedGroovydoc.configure { Groovydoc gdoc ->
     gdoc.windowTitle = "Grails $projectVersion"
     gdoc.docTitle = "Grails $projectVersion"
-    gdoc.footer = '''<!-- Matomo -->
-<script>
-    var _paq = window._paq = window._paq || [];
-    /* tracker methods like "setCustomDimension" should be called before 
"trackPageView" */
-    _paq.push(["setDoNotTrack", true]);
-    _paq.push(["disableCookies"]);
-    _paq.push(['trackPageView']);
-    _paq.push(['enableLinkTracking']);
-    (function() {
-        var u="https://analytics.apache.org/";;
-        _paq.push(['setTrackerUrl', u+'matomo.php']);
-        _paq.push(['setSiteId', '79']);
-        var d=document, g=d.createElement('script'), 
s=d.getElementsByTagName('script')[0];
-        g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
-    })();
-</script>
-<!-- End Matomo Code -->'''
 
     def docProjects = rootProject.subprojects
             .findAll { it.findProperty('includeInApiDocs') }
@@ -127,7 +110,9 @@ combinedGroovydoc.configure { Groovydoc gdoc ->
                 sourceDirs
             }
 
-    gdoc.source(project.files((baseSourceDirs + 
includedBuildSourceDirs).unique()))
+    def allSourceDirs = (baseSourceDirs + includedBuildSourceDirs).unique()
+    gdoc.source(project.files(allSourceDirs))
+    gdoc.ext.groovydocSourceDirs = allSourceDirs
 
     gdoc.classpath = files(sources.collect { SourceSet it -> 
it.compileClasspath.filter(File.&isDirectory) }.flatten().unique())
     gdoc.destinationDir = 
project.layout.buildDirectory.dir('combined-api/api').get().asFile
diff --git a/grails-forge/gradle/doc-config.gradle 
b/grails-forge/gradle/doc-config.gradle
index d7b0eaf7fb..d850444c62 100644
--- a/grails-forge/gradle/doc-config.gradle
+++ b/grails-forge/gradle/doc-config.gradle
@@ -17,46 +17,21 @@
  *  under the License.
  */
 
-configurations.register('documentation') {
-    canBeConsumed = false
-    canBeResolved = true
-    attributes {
-        attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category, 
Category.LIBRARY))
-        attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling, 
Bundling.EXTERNAL))
-        attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, 
Usage.JAVA_RUNTIME))
-    }
+apply plugin: 'org.apache.grails.buildsrc.groovydoc'
+
+groovydocEnhancer {
+    javaVersionEnabled = false
 }
 
 dependencies {
     documentation "org.codehaus.groovy:groovy-templates:$groovyVersion"
     documentation "org.codehaus.groovy:groovy-dateutil:$groovyVersion"
+    documentation "org.codehaus.groovy:groovy-ant:$groovyVersion"
+    documentation "org.codehaus.groovy:groovy-groovydoc:$groovyVersion"
 }
 
-tasks.withType(Groovydoc).configureEach {
-    classpath += project.configurations.documentation
-    windowTitle = "${project.findProperty('pomArtifactId') ?: project.name} - 
$projectVersion"
-    docTitle = "${project.findProperty('pomArtifactId') ?: project.name} - 
$projectVersion"
-    footer = '''<!-- Matomo -->
-<script>
-    var _paq = window._paq = window._paq || [];
-    /* tracker methods like "setCustomDimension" should be called before 
"trackPageView" */
-    _paq.push(["setDoNotTrack", true]);
-    _paq.push(["disableCookies"]);
-    _paq.push(['trackPageView']);
-    _paq.push(['enableLinkTracking']);
-    (function() {
-        var u="https://analytics.apache.org/";;
-        _paq.push(['setTrackerUrl', u+'matomo.php']);
-        _paq.push(['setSiteId', '79']);
-        var d=document, g=d.createElement('script'), 
s=d.getElementsByTagName('script')[0];
-        g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
-    })();
-</script>
-<!-- End Matomo Code -->'''
-    access = GroovydocAccess.PROTECTED
-    includeAuthor = false
-    includeMainForScripts = false
-    processScripts = false
-    noTimestamp = true
-    noVersionStamp = false
+tasks.withType(Groovydoc).configureEach { Groovydoc gdoc ->
+    gdoc.classpath += project.configurations.documentation
+    gdoc.windowTitle = "${project.findProperty('pomArtifactId') ?: 
project.name} - $projectVersion"
+    gdoc.docTitle = "${project.findProperty('pomArtifactId') ?: project.name} 
- $projectVersion"
 }
diff --git a/grails-gradle/gradle/docs-config.gradle 
b/grails-gradle/gradle/docs-config.gradle
index be2aaf4f1c..8426b70a63 100644
--- a/grails-gradle/gradle/docs-config.gradle
+++ b/grails-gradle/gradle/docs-config.gradle
@@ -17,15 +17,8 @@
  *  under the License.
  */
 
-configurations.register('documentation') {
-    canBeConsumed = false
-    canBeResolved = true
-    attributes {
-        attribute(Category.CATEGORY_ATTRIBUTE, objects.named(Category, 
Category.LIBRARY))
-        attribute(Bundling.BUNDLING_ATTRIBUTE, objects.named(Bundling, 
Bundling.EXTERNAL))
-        attribute(Usage.USAGE_ATTRIBUTE, objects.named(Usage, 
Usage.JAVA_RUNTIME))
-    }
-}
+apply plugin: 'org.apache.grails.buildsrc.groovydoc'
+
 dependencies {
     add('documentation', platform(project(':grails-gradle-bom')))
     add('documentation', 'org.fusesource.jansi:jansi')
@@ -45,30 +38,6 @@ ext {
 TaskProvider<Groovydoc> groovydocTask = tasks.named('groovydoc', Groovydoc)
 groovydocTask.configure { Groovydoc it ->
     it.classpath = configurations.documentation
-    it.groovyClasspath = configurations.documentation
-    it.access = GroovydocAccess.PROTECTED
-    it.includeAuthor = false
-    it.includeMainForScripts = false
-    it.processScripts = false
-    it.noTimestamp = true
-    it.noVersionStamp = false
-    it.footer = '''<!-- Matomo -->
-<script>
-    var _paq = window._paq = window._paq || [];
-    /* tracker methods like "setCustomDimension" should be called before 
"trackPageView" */
-    _paq.push(["setDoNotTrack", true]);
-    _paq.push(["disableCookies"]);
-    _paq.push(['trackPageView']);
-    _paq.push(['enableLinkTracking']);
-    (function() {
-        var u="https://analytics.apache.org/";;
-        _paq.push(['setTrackerUrl', u+'matomo.php']);
-        _paq.push(['setSiteId', '79']);
-        var d=document, g=d.createElement('script'), 
s=d.getElementsByTagName('script')[0];
-        g.async=true; g.src=u+'matomo.js'; s.parentNode.insertBefore(g,s);
-    })();
-</script>
-<!-- End Matomo Code -->'''
     it.destinationDir = project.file('build/docs/api')
 }
 


Reply via email to