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

borinquenkid pushed a commit to branch 8.0.x-hibernate7-dev
in repository https://gitbox.apache.org/repos/asf/grails-core.git

commit ff08b7355eb51529b624ae57a89c473a5e854997
Author: Walter Duque de Estrada <[email protected]>
AuthorDate: Tue Mar 10 14:20:59 2026 -0500

    hibernate 7:  added more robustness to ChangeLogParser
---
 .../liquibase/GroovyChangeLogParser.groovy         |   6 +-
 .../database/HibernateSpringBeanDatabase.java      |  22 +--
 .../liquibase/GroovyChangeLogParserSpec.groovy     | 157 +++++++++++++++++++++
 3 files changed, 169 insertions(+), 16 deletions(-)

diff --git 
a/grails-data-hibernate7/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/liquibase/GroovyChangeLogParser.groovy
 
b/grails-data-hibernate7/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/liquibase/GroovyChangeLogParser.groovy
index ce94c92f45..47bcafcd0d 100644
--- 
a/grails-data-hibernate7/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/liquibase/GroovyChangeLogParser.groovy
+++ 
b/grails-data-hibernate7/dbmigration/src/main/groovy/org/grails/plugins/databasemigration/liquibase/GroovyChangeLogParser.groovy
@@ -50,7 +50,11 @@ class GroovyChangeLogParser extends AbstractChangeLogParser {
         def inputStream = null
         def changeLogText = null
         try {
-            inputStream = resourceAccessor.openStreams(null, 
physicalChangeLogLocation).first()
+            def inputStreamList = resourceAccessor.openStreams(null, 
physicalChangeLogLocation)
+            if (inputStreamList == null || inputStreamList.isEmpty()) {
+                throw new ChangeLogParseException("Could not find 
physicalChangeLogLocation: ${physicalChangeLogLocation}")
+            }
+            inputStream = inputStreamList.first()
             changeLogText = inputStream?.text
         } finally {
             IOUtils.closeQuietly(inputStream)
diff --git 
a/grails-data-hibernate7/dbmigration/src/main/java/liquibase/ext/hibernate/database/HibernateSpringBeanDatabase.java
 
b/grails-data-hibernate7/dbmigration/src/main/java/liquibase/ext/hibernate/database/HibernateSpringBeanDatabase.java
index 7212c62614..7c08d734ec 100644
--- 
a/grails-data-hibernate7/dbmigration/src/main/java/liquibase/ext/hibernate/database/HibernateSpringBeanDatabase.java
+++ 
b/grails-data-hibernate7/dbmigration/src/main/java/liquibase/ext/hibernate/database/HibernateSpringBeanDatabase.java
@@ -130,14 +130,10 @@ public class HibernateSpringBeanDatabase extends 
HibernateDatabase {
                         try {
                             
Scope.getCurrentScope().getLog(getClass()).info("Found mappingLocation " + 
mappingLocation);
                             Resource[] resources = 
resourcePatternResolver.getResources(mappingLocation);
-                            if (resources != null) {
-                                for (Resource resource : resources) {
-                                    URL url = resource.getURL();
-                                    if (url != null) {
-                                        
Scope.getCurrentScope().getLog(getClass()).info("Adding resource  " + url);
-                                        sources.addURL(url);
-                                    }
-                                }
+                            for (Resource resource : resources) {
+                                URL url = resource.getURL();
+                                
Scope.getCurrentScope().getLog(getClass()).info("Adding resource  " + url);
+                                sources.addURL(url);
                             }
                         } catch (IOException e) {
                             throw new RuntimeException(e);
@@ -162,17 +158,13 @@ public class HibernateSpringBeanDatabase extends 
HibernateDatabase {
     }
 
     private Class<?> findClass(String className) {
-        return findClass(className, Object.class);
-    }
-
-    private <T> Class<? extends T> findClass(String className, Class<T> 
superClass) {
         try {
             Class<?> newClass = Class.forName(className);
-            if (superClass.isAssignableFrom(newClass)) {
-                return newClass.asSubclass(superClass);
+            if (Object.class.isAssignableFrom(newClass)) {
+                return newClass.asSubclass(Object.class);
             } else {
                 throw new IllegalStateException("The provided class '" + 
className + "' is not assignable from the '"
-                        + superClass.getName() + "' superclass.");
+                        + Object.class.getName() + "' superclass.");
             }
         } catch (ClassNotFoundException e) {
             throw new IllegalStateException(
diff --git 
a/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/liquibase/GroovyChangeLogParserSpec.groovy
 
b/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/liquibase/GroovyChangeLogParserSpec.groovy
new file mode 100644
index 0000000000..ffbf0f35ac
--- /dev/null
+++ 
b/grails-data-hibernate7/dbmigration/src/test/groovy/org/grails/plugins/databasemigration/liquibase/GroovyChangeLogParserSpec.groovy
@@ -0,0 +1,157 @@
+/*
+ *  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.grails.plugins.databasemigration.liquibase
+
+import grails.config.ConfigMap
+import liquibase.changelog.ChangeLogParameters
+import liquibase.exception.ChangeLogParseException
+import liquibase.parser.core.ParsedNode
+import liquibase.resource.InputStreamList
+import liquibase.resource.ResourceAccessor
+import org.springframework.context.ApplicationContext
+import spock.lang.Specification
+
+class GroovyChangeLogParserSpec extends Specification {
+
+    GroovyChangeLogParser parser
+    ResourceAccessor resourceAccessor = Mock()
+    ApplicationContext applicationContext = Mock()
+    ConfigMap config = Mock()
+
+    def setup() {
+        parser = new GroovyChangeLogParser()
+        parser.applicationContext = applicationContext
+        parser.config = config
+    }
+
+    def "supports groovy files"() {
+        expect:
+        parser.supports("changelog.groovy", resourceAccessor)
+        !parser.supports("changelog.xml", resourceAccessor)
+        !parser.supports("changelog.sql", resourceAccessor)
+    }
+
+    def "parses a simple groovy changelog to ParsedNode"() {
+        given:
+        String changelogText = """
+databaseChangeLog = {
+    changeSet(author: "test", id: "1") {
+        createTable(tableName: "test_table") {
+            column(name: "id", type: "int")
+        }
+    }
+}
+"""
+        String location = "changelog.groovy"
+        ChangeLogParameters changeLogParameters = Mock()
+        InputStream inputStream = new 
ByteArrayInputStream(changelogText.getBytes("UTF-8"))
+        InputStreamList inputStreamList = new InputStreamList(new URI("file:" 
+ location), inputStream)
+
+        when:
+        ParsedNode node = parser.parseToNode(location, changeLogParameters, 
resourceAccessor)
+
+        then:
+        1 * resourceAccessor.openStreams(null, location) >> inputStreamList
+        1 * config.getProperty('changelogProperties', Map) >> [:]
+        node != null
+        node.name == "databaseChangeLog"
+        node.children.size() == 1
+        node.children[0].name == "changeSet"
+        node.children[0].getChildValue(null, "author") == "test"
+        node.children[0].getChildValue(null, "id") == "1"
+    }
+
+    def "parses groovy changelog with properties"() {
+        given:
+        String changelogText = """
+databaseChangeLog = {
+    changeSet(author: authorName, id: "1") {
+        addColumn(tableName: "test_table") {
+            column(name: "new_col", type: "varchar(255)")
+        }
+    }
+}
+"""
+        String location = "changelog.groovy"
+        ChangeLogParameters changeLogParameters = Mock()
+        InputStream inputStream = new 
ByteArrayInputStream(changelogText.getBytes("UTF-8"))
+        InputStreamList inputStreamList = new InputStreamList(new URI("file:" 
+ location), inputStream)
+
+        when:
+        ParsedNode node = parser.parseToNode(location, changeLogParameters, 
resourceAccessor)
+
+        then:
+        1 * resourceAccessor.openStreams(null, location) >> inputStreamList
+        1 * config.getProperty('changelogProperties', Map) >> [authorName: 
"John Doe"]
+        1 * changeLogParameters.set("authorName", "John Doe", null, null, 
null, true, null)
+        node != null
+        node.children[0].getChildValue(null, "author") == "John Doe"
+    }
+
+    def "parses groovy changelog with complex property map"() {
+        given:
+        String changelogText = """
+databaseChangeLog = {
+    property(name: "foo", value: propValue)
+}
+"""
+        String location = "changelog.groovy"
+        ChangeLogParameters changeLogParameters = Mock()
+        InputStream inputStream = new 
ByteArrayInputStream(changelogText.getBytes("UTF-8"))
+        InputStreamList inputStreamList = new InputStreamList(new URI("file:" 
+ location), inputStream)
+
+        when:
+        parser.parseToNode(location, changeLogParameters, resourceAccessor)
+
+        then:
+        1 * resourceAccessor.openStreams(null, location) >> inputStreamList
+        1 * config.getProperty('changelogProperties', Map) >> [propValue: 
[value: "bar", contexts: "test", labels: "l1", databases: "h2"]]
+        1 * changeLogParameters.set("propValue", "bar", "test", "l1", "h2", 
true, null)
+    }
+
+    def "throws ChangeLogParseException on invalid script"() {
+        given:
+        String changelogText = "this is not valid groovy"
+        String location = "changelog.groovy"
+        InputStream inputStream = new 
ByteArrayInputStream(changelogText.getBytes("UTF-8"))
+        InputStreamList inputStreamList = new InputStreamList(new URI("file:" 
+ location), inputStream)
+
+        when:
+        parser.parseToNode(location, new ChangeLogParameters(), 
resourceAccessor)
+
+        then:
+        1 * resourceAccessor.openStreams(null, location) >> inputStreamList
+        1 * config.getProperty('changelogProperties', Map) >> [:]
+        thrown(ChangeLogParseException)
+    }
+
+    def "throws ChangeLogParseException when openStreams is empty"() {
+        given:
+        String location = "missing.groovy"
+        InputStreamList inputStreamList = new InputStreamList()
+
+        when:
+        parser.parseToNode(location, new ChangeLogParameters(), 
resourceAccessor)
+
+        then:
+        1 * resourceAccessor.openStreams(null, location) >> inputStreamList
+        def e = thrown(ChangeLogParseException)
+        e.message.contains("Could not find physicalChangeLogLocation: 
missing.groovy")
+    }
+}

Reply via email to