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

jdaugherty pushed a commit to branch corrupt-jar-fixes
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit 611227e8830380838109eebe629128421690faa4
Author: James Daugherty <[email protected]>
AuthorDate: Thu May 15 16:27:25 2025 -0400

    update find main class task and strictly validate the existence
---
 .../org/grails/io/support/MainClassFinder.groovy   | 32 ++++----
 .../gradle/plugin/core/GrailsGradlePlugin.groovy   | 90 +++++++++++++++-------
 .../gradle/plugin/run/FindMainClassTask.groovy     | 75 +++++++++++-------
 3 files changed, 129 insertions(+), 68 deletions(-)

diff --git 
a/grails-gradle/model/src/main/groovy/org/grails/io/support/MainClassFinder.groovy
 
b/grails-gradle/model/src/main/groovy/org/grails/io/support/MainClassFinder.groovy
index eadb7a006c..5c16d71a31 100644
--- 
a/grails-gradle/model/src/main/groovy/org/grails/io/support/MainClassFinder.groovy
+++ 
b/grails-gradle/model/src/main/groovy/org/grails/io/support/MainClassFinder.groovy
@@ -1,27 +1,29 @@
 /*
- *  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
+ *  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
+ *      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.
+ *  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.grails.io.support
 
 import grails.util.BuildSettings
 import groovy.transform.CompileStatic
-import groovyjarjarasm.asm.*
+import groovyjarjarasm.asm.ClassReader
+import groovyjarjarasm.asm.ClassVisitor
+import groovyjarjarasm.asm.MethodVisitor
+import groovyjarjarasm.asm.Opcodes
+import groovyjarjarasm.asm.Type
 
 import java.nio.file.Paths
 import java.util.concurrent.ConcurrentHashMap
diff --git 
a/grails-gradle/plugins/src/main/groovy/org/grails/gradle/plugin/core/GrailsGradlePlugin.groovy
 
b/grails-gradle/plugins/src/main/groovy/org/grails/gradle/plugin/core/GrailsGradlePlugin.groovy
index 89b9cf6424..c44253a4c4 100644
--- 
a/grails-gradle/plugins/src/main/groovy/org/grails/gradle/plugin/core/GrailsGradlePlugin.groovy
+++ 
b/grails-gradle/plugins/src/main/groovy/org/grails/gradle/plugin/core/GrailsGradlePlugin.groovy
@@ -1,20 +1,18 @@
 /*
- *  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
+ *  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
+ *      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.
+ *  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.grails.gradle.plugin.core
 
@@ -28,7 +26,11 @@ import 
io.spring.gradle.dependencymanagement.DependencyManagementPlugin
 import io.spring.gradle.dependencymanagement.dsl.DependencyManagementExtension
 import org.apache.tools.ant.filters.EscapeUnicode
 import org.apache.tools.ant.filters.ReplaceTokens
-import org.gradle.api.*
+import org.gradle.api.Action
+import org.gradle.api.NamedDomainObjectProvider
+import org.gradle.api.Plugin
+import org.gradle.api.Project
+import org.gradle.api.Task
 import org.gradle.api.artifacts.Configuration
 import org.gradle.api.artifacts.Dependency
 import org.gradle.api.artifacts.DependencyResolveDetails
@@ -39,7 +41,12 @@ import org.gradle.api.file.RegularFile
 import org.gradle.api.plugins.ExtraPropertiesExtension
 import org.gradle.api.plugins.GroovyPlugin
 import org.gradle.api.provider.Provider
-import org.gradle.api.tasks.*
+import org.gradle.api.tasks.AbstractCopyTask
+import org.gradle.api.tasks.JavaExec
+import org.gradle.api.tasks.SourceSet
+import org.gradle.api.tasks.SourceSetOutput
+import org.gradle.api.tasks.TaskContainer
+import org.gradle.api.tasks.TaskProvider
 import org.gradle.api.tasks.compile.GroovyCompile
 import org.gradle.api.tasks.testing.Test
 import org.gradle.language.jvm.tasks.ProcessResources
@@ -54,7 +61,10 @@ import org.grails.gradle.plugin.run.FindMainClassTask
 import org.grails.gradle.plugin.util.SourceSets
 import org.grails.io.support.FactoriesLoaderSupport
 import org.springframework.boot.gradle.dsl.SpringBootExtension
+import org.springframework.boot.gradle.plugin.ResolveMainClassName
 import org.springframework.boot.gradle.plugin.SpringBootPlugin
+import org.springframework.boot.gradle.tasks.bundling.BootArchive
+import org.springframework.boot.gradle.tasks.run.BootRun
 
 import javax.inject.Inject
 
@@ -342,13 +352,12 @@ class GrailsGradlePlugin extends GroovyPlugin {
     protected void configureMicronaut(Project project) {
         final String micronautVersion = project.properties['micronautVersion']
         if (micronautVersion) {
-            project.configurations.all({ Configuration configuration ->
+            project.configurations.configureEach({ Configuration configuration 
->
                 configuration.resolutionStrategy.eachDependency({ 
DependencyResolveDetails details ->
                     String dependencyName = details.requested.name
                     String group = details.requested.group
                     if (group == 'io.micronaut' && 
dependencyName.startsWith('micronaut')) {
                         details.useVersion(micronautVersion)
-                        return
                     }
                 } as Action<DependencyResolveDetails>)
             } as Action<Configuration>)
@@ -533,6 +542,11 @@ class GrailsGradlePlugin extends GroovyPlugin {
     protected void configureConsoleTask(Project project) {
         TaskContainer tasks = project.tasks
         if (!project.configurations.names.contains('console')) {
+            if (!tasks.names.contains('findMainClass')) {
+                project.logger.info("Project ${project.name} does not contain 
the findMainClass task so the console & shell tasks will not be created.")
+                return
+            }
+
             NamedDomainObjectProvider<Configuration> consoleConfiguration = 
project.configurations.register('console')
             def consoleTask = createConsoleTask(project, tasks, 
consoleConfiguration)
             def shellTask = createShellTask(project, tasks, 
consoleConfiguration)
@@ -540,6 +554,10 @@ class GrailsGradlePlugin extends GroovyPlugin {
             tasks.named('findMainClass').configure {
                 it.doLast {
                     ExtraPropertiesExtension extraProperties = 
(ExtraPropertiesExtension) project.getExtensions().getByName("ext")
+                    if (!extraProperties.has('mainClassName')) {
+                        return // disabled because we don't expect to run a 
grails app (likely a plugin)
+                    }
+
                     def mainClassName = extraProperties.get('mainClassName')
                     if (mainClassName) {
                         consoleTask.get().args mainClassName
@@ -597,14 +615,34 @@ class GrailsGradlePlugin extends GroovyPlugin {
 
     protected void registerFindMainClassTask(Project project) {
         TaskContainer taskContainer = project.tasks
-        def findMainClassTask = taskContainer.findByName("findMainClass")
-        if (findMainClassTask == null) {
-            findMainClassTask = project.tasks.register("findMainClass", 
FindMainClassTask).get()
-            
findMainClassTask.mustRunAfter(project.tasks.withType(GroovyCompile))
-        } else if 
(!FindMainClassTask.class.isAssignableFrom(findMainClassTask.class)) {
-            def grailsFindMainClass = 
project.tasks.register("grailsFindMainClass", FindMainClassTask).get()
-            grailsFindMainClass.dependsOn(findMainClassTask)
-            findMainClassTask.finalizedBy(grailsFindMainClass)
+
+        def existingTask = taskContainer.findByName("findMainClass")
+        if (existingTask == null) {
+            TaskProvider<FindMainClassTask> findMainClassTask = 
project.tasks.register("findMainClass", FindMainClassTask)
+
+            Provider<RegularFile> mainClassFileContainer = 
project.layout.buildDirectory.file('resolvedMainClassName')
+            Provider<String> mainClassProvider = 
project.providers.fileContents(mainClassFileContainer).asText.map {
+                it.trim()
+            }
+            project.tasks.withType(BootArchive).configureEach { BootArchive 
bootTask ->
+                bootTask.dependsOn(findMainClassTask)
+                bootTask.inputs.file(mainClassFileContainer)
+                bootTask.mainClass.convention(mainClassProvider)
+            }
+            project.tasks.withType(BootRun).configureEach { BootRun it ->
+                it.dependsOn(findMainClassTask)
+                it.inputs.file(mainClassFileContainer)
+                it.mainClass.convention(mainClassProvider)
+            }
+
+            findMainClassTask.configure {
+                it.mustRunAfter(project.tasks.withType(GroovyCompile))
+            }
+            project.tasks.withType(ResolveMainClassName).configureEach {
+                it.dependsOn findMainClassTask
+            }
+        } else if 
(!FindMainClassTask.class.isAssignableFrom(existingTask.class)) {
+            project.logger.warn("Grails Projects typically register a 
findMainClass task to force the MainClass resolution for Spring Boot. This task 
already exists so this will not occur.")
         }
     }
 
diff --git 
a/grails-gradle/plugins/src/main/groovy/org/grails/gradle/plugin/run/FindMainClassTask.groovy
 
b/grails-gradle/plugins/src/main/groovy/org/grails/gradle/plugin/run/FindMainClassTask.groovy
index 1e42fd9961..79713f75ff 100644
--- 
a/grails-gradle/plugins/src/main/groovy/org/grails/gradle/plugin/run/FindMainClassTask.groovy
+++ 
b/grails-gradle/plugins/src/main/groovy/org/grails/gradle/plugin/run/FindMainClassTask.groovy
@@ -1,20 +1,18 @@
 /*
- *  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
+ *  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
+ *      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.
+ *  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.grails.gradle.plugin.run
 
@@ -25,10 +23,18 @@ import org.gradle.api.file.FileCollection
 import org.gradle.api.file.RegularFile
 import org.gradle.api.plugins.ExtraPropertiesExtension
 import org.gradle.api.provider.Provider
-import org.gradle.api.tasks.*
+import org.gradle.api.tasks.CacheableTask
+import org.gradle.api.tasks.InputFiles
+import org.gradle.api.tasks.OutputFile
+import org.gradle.api.tasks.PathSensitive
+import org.gradle.api.tasks.PathSensitivity
+import org.gradle.api.tasks.SourceSet
+import org.gradle.api.tasks.SourceSetOutput
+import org.gradle.api.tasks.TaskAction
 import org.grails.gradle.plugin.util.SourceSets
 import org.grails.io.support.MainClassFinder
-import org.springframework.boot.gradle.tasks.run.BootRun
+import org.springframework.boot.gradle.dsl.SpringBootExtension
+import org.springframework.boot.gradle.plugin.SpringBootPlugin
 
 /**
  * A task that finds the main task, differs slightly from Boot's version as 
expects a subclass of GrailsConfiguration
@@ -43,14 +49,29 @@ class FindMainClassTask extends DefaultTask {
     @TaskAction
     void setMainClassProperty() {
         Project project = this.project
-        if(project.tasks.names.contains('bootRun')) {
-            BootRun bootRun = project.tasks.named("bootRun", BootRun).get()
-            String mainClass = findMainClass()
-            if (mainClass != null) {
-                bootRun.mainClass.set(mainClass)
-                ExtraPropertiesExtension extraProperties = 
(ExtraPropertiesExtension) project.getExtensions().getByName("ext")
-                extraProperties.set("mainClassName", mainClass)
-            }
+
+        def bootRunTask = project.tasks.findByName('bootRun')
+        if (!bootRunTask || !bootRunTask.enabled) {
+            project.logger.info('The bootRun task will not so this must not be 
a runnable grails application. Skipping finding main class.')
+            return
+        }
+
+        def bootJarTask = 
project.tasks.findByName(SpringBootPlugin.BOOT_JAR_TASK_NAME)
+        def bootWarTask = 
project.tasks.findByName(SpringBootPlugin.BOOT_WAR_TASK_NAME)
+        if ((!bootJarTask || !bootJarTask.enabled) && (!bootWarTask || 
!bootWarTask.enabled)) {
+            project.logger.info("There is neither a 
${SpringBootPlugin.BOOT_JAR_TASK_NAME} or 
${SpringBootPlugin.BOOT_WAR_TASK_NAME} task that will run. Skipping finding 
main Application class.")
+            return
+        }
+
+        String mainClass = findMainClass()
+        if (mainClass) {
+            ExtraPropertiesExtension extraProperties = 
(ExtraPropertiesExtension) project.getExtensions().getByName('ext')
+            extraProperties.set('mainClassName', mainClass)
+
+            SpringBootExtension springBootExtension = 
project.getExtensions().getByType(SpringBootExtension)
+            springBootExtension.mainClass.convention(mainClass)
+        } else {
+            project.logger.warn("No main class found. Please set 
'springBoot.mainClass'.")
         }
     }
 
@@ -67,7 +88,7 @@ class FindMainClassTask extends DefaultTask {
 
     @OutputFile
     Provider<RegularFile> getMainClassCacheFile() {
-        project.layout.buildDirectory.file('.mainClass')
+        project.layout.buildDirectory.file('resolvedMainClassName')
     }
 
     protected String findMainClass() {
@@ -103,7 +124,7 @@ class FindMainClassTask extends DefaultTask {
                 if (mainClass != null) {
                     mainClassFile.text = mainClass
                 } else {
-                    throw new RuntimeException("Could not find Application 
main class. Please set 'springBoot.mainClass'.")
+                    throw new RuntimeException("Could not find Application 
main class. Please set 'springBoot.mainClass' or disable BootJar & BootArchive 
tasks.")
                 }
             }
             return mainClass
@@ -111,7 +132,7 @@ class FindMainClassTask extends DefaultTask {
     }
 
     protected FileCollection resolveClassesDirs(SourceSetOutput output, 
Project project) {
-        output?.classesDirs ?: project.files(new File(project.buildDir, 
"classes/main"))
+        output?.classesDirs ?: project.files(new File(project.buildDir, 
'classes/main'))
     }
 
     protected MainClassFinder createMainClassFinder() {

Reply via email to